* remove little unused code

* code cleanup
This commit is contained in:
giantpune 2010-09-18 23:16:05 +00:00
parent e1a36e8988
commit 9e79c9d99b
326 changed files with 87736 additions and 80266 deletions

View File

@ -2,8 +2,8 @@
<app version="1"> <app version="1">
<name> USB Loader GX</name> <name> USB Loader GX</name>
<coder>USB Loader GX Team</coder> <coder>USB Loader GX Team</coder>
<version>1.0 r950</version> <version>1.0 r951</version>
<release_date>201009182245</release_date> <release_date>201009182308</release_date>
<short_description>Loads games from USB-devices</short_description> <short_description>Loads games from USB-devices</short_description>
<long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times. <long_description>USB Loader GX is a libwiigui based USB iso loader with a wii-like GUI. You can install games to your HDDs and boot them with shorter loading times.
The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller. The interactive GUI is completely controllable with WiiMote, Classic Controller or GC Controller.

BIN
data/magic_patcher.o Normal file

Binary file not shown.

View File

@ -27,55 +27,55 @@
#include "filelist.h" #include "filelist.h"
FreeTypeGX * fontSystem = NULL; FreeTypeGX * fontSystem = NULL;
static FT_Byte * MainFont = (FT_Byte *) font_ttf; static FT_Byte * MainFont = ( FT_Byte * ) font_ttf;
static u32 MainFontSize = font_ttf_size; static u32 MainFontSize = font_ttf_size;
void ClearFontData() void ClearFontData()
{ {
if(fontSystem) if ( fontSystem )
delete fontSystem; delete fontSystem;
fontSystem = NULL; fontSystem = NULL;
if(MainFont != (FT_Byte *) font_ttf) if ( MainFont != ( FT_Byte * ) font_ttf )
{ {
if(MainFont != NULL) if ( MainFont != NULL )
delete [] MainFont; delete [] MainFont;
MainFont = (FT_Byte *) font_ttf; MainFont = ( FT_Byte * ) font_ttf;
MainFontSize = font_ttf_size; MainFontSize = font_ttf_size;
} }
} }
bool SetupDefaultFont(const char *path) bool SetupDefaultFont( const char *path )
{ {
bool result = false; bool result = false;
FILE *pfile = NULL; FILE *pfile = NULL;
ClearFontData(); ClearFontData();
if(path) if ( path )
pfile = fopen(path, "rb"); pfile = fopen( path, "rb" );
if(pfile) if ( pfile )
{ {
fseek(pfile, 0, SEEK_END); fseek( pfile, 0, SEEK_END );
MainFontSize = ftell(pfile); MainFontSize = ftell( pfile );
rewind(pfile); rewind( pfile );
MainFont = new (std::nothrow) FT_Byte[MainFontSize]; MainFont = new ( std::nothrow ) FT_Byte[MainFontSize];
if(!MainFont) if ( !MainFont )
{ {
MainFont = (FT_Byte *) font_ttf; MainFont = ( FT_Byte * ) font_ttf;
MainFontSize = font_ttf_size; MainFontSize = font_ttf_size;
} }
else else
{ {
fread(MainFont, 1, MainFontSize, pfile); fread( MainFont, 1, MainFontSize, pfile );
result = true; result = true;
} }
fclose(pfile); fclose( pfile );
} }
fontSystem = new FreeTypeGX(MainFont, MainFontSize); fontSystem = new FreeTypeGX( MainFont, MainFontSize );
return result; return result;
} }

View File

@ -26,7 +26,7 @@
#ifndef FONTSYSTEM_H_ #ifndef FONTSYSTEM_H_
#define FONTSYSTEM_H_ #define FONTSYSTEM_H_
bool SetupDefaultFont(const char *path); bool SetupDefaultFont( const char *path );
void ClearFontData(); void ClearFontData();
#endif #endif

View File

@ -30,44 +30,44 @@ using namespace std;
* This routine converts a supplied short character string into a wide character string. * This routine converts a supplied short character string into a wide character string.
* Note that it is the user's responsibility to clear the returned buffer once it is no longer needed. * Note that it is the user's responsibility to clear the returned buffer once it is no longer needed.
* *
* @param strChar Character string to be converted. * @param strChar Character string to be converted.
* @return Wide character representation of supplied character string. * @return Wide character representation of supplied character string.
*/ */
wchar_t* charToWideChar(const char* strChar) wchar_t* charToWideChar( const char* strChar )
{ {
if(!strChar) if ( !strChar )
return NULL; return NULL;
wchar_t *strWChar = new (std::nothrow) wchar_t[strlen(strChar) + 1]; wchar_t *strWChar = new ( std::nothrow ) wchar_t[strlen( strChar ) + 1];
if(!strWChar) if ( !strWChar )
return NULL; return NULL;
int bt = mbstowcs(strWChar, strChar, strlen(strChar)); int bt = mbstowcs( strWChar, strChar, strlen( strChar ) );
if (bt > 0) if ( bt > 0 )
{ {
strWChar[bt] = 0; strWChar[bt] = 0;
return strWChar; return strWChar;
} }
wchar_t *tempDest = strWChar; wchar_t *tempDest = strWChar;
while((*tempDest++ = *strChar++)); while ( ( *tempDest++ = *strChar++ ) );
return strWChar; return strWChar;
} }
/** /**
* Default constructor for the FreeTypeGX class for WiiXplorer. * Default constructor for the FreeTypeGX class for WiiXplorer.
*/ */
FreeTypeGX::FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize) FreeTypeGX::FreeTypeGX( const uint8_t* fontBuffer, FT_Long bufferSize )
{ {
ftPointSize = 0; ftPointSize = 0;
FT_Init_FreeType(&ftLibrary); FT_Init_FreeType( &ftLibrary );
FT_New_Memory_Face(ftLibrary, (FT_Byte *)fontBuffer, bufferSize, 0, &ftFace); FT_New_Memory_Face( ftLibrary, ( FT_Byte * )fontBuffer, bufferSize, 0, &ftFace );
setVertexFormat(GX_VTXFMT1); setVertexFormat( GX_VTXFMT1 );
ftKerningEnabled = FT_HAS_KERNING(ftFace); ftKerningEnabled = FT_HAS_KERNING( ftFace );
} }
/** /**
@ -75,9 +75,9 @@ FreeTypeGX::FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize)
*/ */
FreeTypeGX::~FreeTypeGX() FreeTypeGX::~FreeTypeGX()
{ {
unloadFont(); unloadFont();
FT_Done_Face(ftFace); FT_Done_Face( ftFace );
FT_Done_FreeType(ftLibrary); FT_Done_FreeType( ftLibrary );
} }
/** /**
@ -87,14 +87,14 @@ FreeTypeGX::~FreeTypeGX()
* Note that this function should not need to be called except if the vertex formats are cleared or the specified * Note that this function should not need to be called except if the vertex formats are cleared or the specified
* vertex format index is modified. * vertex format index is modified.
* *
* @param vertexIndex Vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file. * @param vertexIndex Vertex format index (GX_VTXFMT*) of the glyph textures as defined by the libogc gx.h header file.
*/ */
void FreeTypeGX::setVertexFormat(uint8_t vertexInd) void FreeTypeGX::setVertexFormat( uint8_t vertexInd )
{ {
vertexIndex = vertexInd; vertexIndex = vertexInd;
GX_SetVtxAttrFmt(vertexIndex, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); GX_SetVtxAttrFmt( vertexIndex, GX_VA_POS, GX_POS_XYZ, GX_S16, 0 );
GX_SetVtxAttrFmt(vertexIndex, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); GX_SetVtxAttrFmt( vertexIndex, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0 );
GX_SetVtxAttrFmt(vertexIndex, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); GX_SetVtxAttrFmt( vertexIndex, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0 );
} }
/** /**
@ -104,22 +104,22 @@ void FreeTypeGX::setVertexFormat(uint8_t vertexInd)
*/ */
void FreeTypeGX::unloadFont() void FreeTypeGX::unloadFont()
{ {
if(this->fontData.size() == 0) if ( this->fontData.size() == 0 )
return; return;
map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr; map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr;
map<wchar_t, ftgxCharData>::iterator itr2; map<wchar_t, ftgxCharData>::iterator itr2;
for(itr = fontData.begin(); itr != fontData.end(); itr++) for ( itr = fontData.begin(); itr != fontData.end(); itr++ )
{ {
for(itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++) for ( itr2 = itr->second.begin(); itr2 != itr->second.end(); itr2++ )
free(itr2->second.glyphDataTexture); free( itr2->second.glyphDataTexture );
itr->second.clear(); itr->second.clear();
} }
fontData.clear(); fontData.clear();
ftgxAlign.clear(); ftgxAlign.clear();
} }
/** /**
@ -128,70 +128,70 @@ void FreeTypeGX::unloadFont()
* This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible * This routine renders and stores the requested glyph's bitmap and relevant information into its own quickly addressible
* structure within an instance-specific map. * structure within an instance-specific map.
* *
* @param charCode The requested glyph's character code. * @param charCode The requested glyph's character code.
* @return A pointer to the allocated font structure. * @return A pointer to the allocated font structure.
*/ */
ftgxCharData * FreeTypeGX::cacheGlyphData(wchar_t charCode, int16_t pixelSize) ftgxCharData * FreeTypeGX::cacheGlyphData( wchar_t charCode, int16_t pixelSize )
{ {
map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr; map<int16_t, map<wchar_t, ftgxCharData> >::iterator itr;
map<wchar_t, ftgxCharData>::iterator itr2; map<wchar_t, ftgxCharData>::iterator itr2;
itr = fontData.find(pixelSize); itr = fontData.find( pixelSize );
if(itr != fontData.end()) if ( itr != fontData.end() )
{ {
itr2 = itr->second.find(charCode); itr2 = itr->second.find( charCode );
if(itr2 != itr->second.end()) if ( itr2 != itr->second.end() )
{ {
return &itr2->second; return &itr2->second;
} }
} }
FT_UInt gIndex; FT_UInt gIndex;
uint16_t textureWidth = 0, textureHeight = 0; uint16_t textureWidth = 0, textureHeight = 0;
if(ftPointSize != pixelSize) if ( ftPointSize != pixelSize )
{ {
ftPointSize = pixelSize; ftPointSize = pixelSize;
FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize); FT_Set_Pixel_Sizes( ftFace, 0, ftPointSize );
//!Cache ascender and decender as well //!Cache ascender and decender as well
map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find(ftPointSize); map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find( ftPointSize );
if(itrAlign == ftgxAlign.end()) if ( itrAlign == ftgxAlign.end() )
{ {
ftgxAlign[ftPointSize].ascender = (int16_t) ftFace->size->metrics.ascender>>6; ftgxAlign[ftPointSize].ascender = ( int16_t ) ftFace->size->metrics.ascender >> 6;
ftgxAlign[ftPointSize].descender = (int16_t) ftFace->size->metrics.descender>>6; ftgxAlign[ftPointSize].descender = ( int16_t ) ftFace->size->metrics.descender >> 6;
ftgxAlign[ftPointSize].max = 0; ftgxAlign[ftPointSize].max = 0;
ftgxAlign[ftPointSize].min = 0; ftgxAlign[ftPointSize].min = 0;
} }
} }
gIndex = FT_Get_Char_Index(ftFace, (FT_ULong) charCode); gIndex = FT_Get_Char_Index( ftFace, ( FT_ULong ) charCode );
if (gIndex != 0 && FT_Load_Glyph(ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER) == 0) if ( gIndex != 0 && FT_Load_Glyph( ftFace, gIndex, FT_LOAD_DEFAULT | FT_LOAD_RENDER ) == 0 )
{ {
if(ftFace->glyph->format == FT_GLYPH_FORMAT_BITMAP) if ( ftFace->glyph->format == FT_GLYPH_FORMAT_BITMAP )
{ {
FT_Bitmap *glyphBitmap = &ftFace->glyph->bitmap; FT_Bitmap *glyphBitmap = &ftFace->glyph->bitmap;
textureWidth = glyphBitmap->width + (4 - glyphBitmap->width % 4) % 4; textureWidth = glyphBitmap->width + ( 4 - glyphBitmap->width % 4 ) % 4;
textureHeight = glyphBitmap->rows + (4 - glyphBitmap->rows % 4) % 4; textureHeight = glyphBitmap->rows + ( 4 - glyphBitmap->rows % 4 ) % 4;
fontData[pixelSize][charCode].renderOffsetX = (int16_t) ftFace->glyph->bitmap_left; fontData[pixelSize][charCode].renderOffsetX = ( int16_t ) ftFace->glyph->bitmap_left;
fontData[pixelSize][charCode].glyphAdvanceX = (uint16_t) (ftFace->glyph->advance.x >> 6); fontData[pixelSize][charCode].glyphAdvanceX = ( uint16_t ) ( ftFace->glyph->advance.x >> 6 );
fontData[pixelSize][charCode].glyphIndex = (uint32_t) gIndex; fontData[pixelSize][charCode].glyphIndex = ( uint32_t ) gIndex;
fontData[pixelSize][charCode].textureWidth = (uint16_t) textureWidth; fontData[pixelSize][charCode].textureWidth = ( uint16_t ) textureWidth;
fontData[pixelSize][charCode].textureHeight = (uint16_t) textureHeight; fontData[pixelSize][charCode].textureHeight = ( uint16_t ) textureHeight;
fontData[pixelSize][charCode].renderOffsetY = (int16_t) ftFace->glyph->bitmap_top; fontData[pixelSize][charCode].renderOffsetY = ( int16_t ) ftFace->glyph->bitmap_top;
fontData[pixelSize][charCode].renderOffsetMax = (int16_t) ftFace->glyph->bitmap_top; fontData[pixelSize][charCode].renderOffsetMax = ( int16_t ) ftFace->glyph->bitmap_top;
fontData[pixelSize][charCode].renderOffsetMin = (int16_t) glyphBitmap->rows - ftFace->glyph->bitmap_top; fontData[pixelSize][charCode].renderOffsetMin = ( int16_t ) glyphBitmap->rows - ftFace->glyph->bitmap_top;
fontData[pixelSize][charCode].glyphDataTexture = NULL; fontData[pixelSize][charCode].glyphDataTexture = NULL;
loadGlyphData(glyphBitmap, &fontData[pixelSize][charCode]); loadGlyphData( glyphBitmap, &fontData[pixelSize][charCode] );
return &fontData[pixelSize][charCode]; return &fontData[pixelSize][charCode];
} }
} }
return NULL; return NULL;
} }
/** /**
@ -200,19 +200,19 @@ ftgxCharData * FreeTypeGX::cacheGlyphData(wchar_t charCode, int16_t pixelSize)
* This routine locates each character in the configured font face and renders the glyph's bitmap. * This routine locates each character in the configured font face and renders the glyph's bitmap.
* Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map. * Each bitmap and relevant information is loaded into its own quickly addressible structure within an instance-specific map.
*/ */
uint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize) uint16_t FreeTypeGX::cacheGlyphDataComplete( int16_t pixelSize )
{ {
uint32_t i = 0; uint32_t i = 0;
FT_UInt gIndex; FT_UInt gIndex;
FT_ULong charCode = FT_Get_First_Char( ftFace, &gIndex ); FT_ULong charCode = FT_Get_First_Char( ftFace, &gIndex );
while ( gIndex != 0 ) while ( gIndex != 0 )
{ {
if(cacheGlyphData(charCode, pixelSize) != NULL) if ( cacheGlyphData( charCode, pixelSize ) != NULL )
++i; ++i;
charCode = FT_Get_Next_Char( ftFace, charCode, &gIndex ); charCode = FT_Get_Next_Char( ftFace, charCode, &gIndex );
} }
return (uint16_t)(i); return ( uint16_t )( i );
} }
/** /**
@ -221,40 +221,40 @@ uint16_t FreeTypeGX::cacheGlyphDataComplete(int16_t pixelSize)
* This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer. * This routine does a simple byte-wise copy of the glyph's rendered 8-bit grayscale bitmap into the structure's buffer.
* Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value. * Each byte is converted from the bitmap's intensity value into the a uint32_t RGBA value.
* *
* @param bmp A pointer to the most recently rendered glyph's bitmap. * @param bmp A pointer to the most recently rendered glyph's bitmap.
* @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph. * @param charData A pointer to an allocated ftgxCharData structure whose data represent that of the last rendered glyph.
* *
* *
* Optimized for RGBA8 use by Dimok. * Optimized for RGBA8 use by Dimok.
*/ */
void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData) void FreeTypeGX::loadGlyphData( FT_Bitmap *bmp, ftgxCharData *charData )
{ {
int length = ((((charData->textureWidth+3)>>2)*((charData->textureHeight+3)>>2)*32*2 + 31) & ~31); int length = ( ( ( ( charData->textureWidth + 3 ) >> 2 ) * ( ( charData->textureHeight + 3 ) >> 2 ) * 32 * 2 + 31 ) & ~31 );
uint8_t * glyphData = (uint8_t *) memalign(32, length); uint8_t * glyphData = ( uint8_t * ) memalign( 32, length );
if(!glyphData) if ( !glyphData )
return; return;
memset(glyphData, 0x00, length); memset( glyphData, 0x00, length );
uint8_t *src = (uint8_t *)bmp->buffer; uint8_t *src = ( uint8_t * )bmp->buffer;
uint32_t offset; uint32_t offset;
for (int imagePosY = 0; imagePosY < bmp->rows; ++imagePosY) for ( int imagePosY = 0; imagePosY < bmp->rows; ++imagePosY )
{ {
for (int imagePosX = 0; imagePosX < bmp->width; ++imagePosX) for ( int imagePosX = 0; imagePosX < bmp->width; ++imagePosX )
{ {
offset = ((((imagePosY >> 2) * (charData->textureWidth >> 2) + (imagePosX >> 2)) << 5) + ((imagePosY & 3) << 2) + (imagePosX & 3)) << 1; offset = ( ( ( ( imagePosY >> 2 ) * ( charData->textureWidth >> 2 ) + ( imagePosX >> 2 ) ) << 5 ) + ( ( imagePosY & 3 ) << 2 ) + ( imagePosX & 3 ) ) << 1;
glyphData[offset] = *src; glyphData[offset] = *src;
glyphData[offset+1] = *src; glyphData[offset+1] = *src;
glyphData[offset+32] = *src; glyphData[offset+32] = *src;
glyphData[offset+33] = *src; glyphData[offset+33] = *src;
++src; ++src;
} }
} }
DCFlushRange(glyphData, length); DCFlushRange( glyphData, length );
charData->glyphDataTexture = glyphData; charData->glyphDataTexture = glyphData;
} }
/** /**
@ -262,18 +262,18 @@ void FreeTypeGX::loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData)
* *
* This routine calculates the x offset of the rendered string based off of a supplied positional format parameter. * This routine calculates the x offset of the rendered string based off of a supplied positional format parameter.
* *
* @param width Current pixel width of the string. * @param width Current pixel width of the string.
* @param format Positional format of the string. * @param format Positional format of the string.
*/ */
int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format) int16_t FreeTypeGX::getStyleOffsetWidth( uint16_t width, uint16_t format )
{ {
if (format & FTGX_JUSTIFY_LEFT) if ( format & FTGX_JUSTIFY_LEFT )
return 0; return 0;
else if (format & FTGX_JUSTIFY_CENTER) else if ( format & FTGX_JUSTIFY_CENTER )
return -(width >> 1); return -( width >> 1 );
else if (format & FTGX_JUSTIFY_RIGHT) else if ( format & FTGX_JUSTIFY_RIGHT )
return -width; return -width;
return 0; return 0;
} }
/** /**
@ -281,40 +281,40 @@ int16_t FreeTypeGX::getStyleOffsetWidth(uint16_t width, uint16_t format)
* *
* This routine calculates the y offset of the rendered string based off of a supplied positional format parameter. * This routine calculates the y offset of the rendered string based off of a supplied positional format parameter.
* *
* @param offset Current pixel offset data of the string. * @param offset Current pixel offset data of the string.
* @param format Positional format of the string. * @param format Positional format of the string.
*/ */
int16_t FreeTypeGX::getStyleOffsetHeight(int16_t format, uint16_t pixelSize) int16_t FreeTypeGX::getStyleOffsetHeight( int16_t format, uint16_t pixelSize )
{ {
map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find(pixelSize); map<int16_t, ftgxDataOffset>::iterator itrAlign = ftgxAlign.find( pixelSize );
if(itrAlign == ftgxAlign.end()) if ( itrAlign == ftgxAlign.end() )
return 0; return 0;
switch(format & FTGX_ALIGN_MASK) switch ( format & FTGX_ALIGN_MASK )
{ {
case FTGX_ALIGN_TOP: case FTGX_ALIGN_TOP:
return itrAlign->second.ascender; return itrAlign->second.ascender;
case FTGX_ALIGN_MIDDLE: case FTGX_ALIGN_MIDDLE:
default: default:
return (itrAlign->second.ascender + itrAlign->second.descender + 1) >> 1; return ( itrAlign->second.ascender + itrAlign->second.descender + 1 ) >> 1;
case FTGX_ALIGN_BOTTOM: case FTGX_ALIGN_BOTTOM:
return itrAlign->second.descender; return itrAlign->second.descender;
case FTGX_ALIGN_BASELINE: case FTGX_ALIGN_BASELINE:
return 0; return 0;
case FTGX_ALIGN_GLYPH_TOP: case FTGX_ALIGN_GLYPH_TOP:
return itrAlign->second.max; return itrAlign->second.max;
case FTGX_ALIGN_GLYPH_MIDDLE: case FTGX_ALIGN_GLYPH_MIDDLE:
return (itrAlign->second.max + itrAlign->second.min + 1) >> 1; return ( itrAlign->second.max + itrAlign->second.min + 1 ) >> 1;
case FTGX_ALIGN_GLYPH_BOTTOM: case FTGX_ALIGN_GLYPH_BOTTOM:
return itrAlign->second.min; return itrAlign->second.min;
} }
return 0; return 0;
} }
/** /**
@ -323,77 +323,77 @@ int16_t FreeTypeGX::getStyleOffsetHeight(int16_t format, uint16_t pixelSize)
* This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer, * This routine processes each character of the supplied text string, loads the relevant preprocessed bitmap buffer,
* a texture from said buffer, and loads the resultant texture into the EFB. * a texture from said buffer, and loads the resultant texture into the EFB.
* *
* @param x Screen X coordinate at which to output the text. * @param x Screen X coordinate at which to output the text.
* @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs. * @param y Screen Y coordinate at which to output the text. Note that this value corresponds to the text string origin and not the top or bottom of the glyphs.
* @param text NULL terminated string to output. * @param text NULL terminated string to output.
* @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff} * @param color Optional color to apply to the text characters. If not specified default value is ftgxWhite: (GXColor){0xff, 0xff, 0xff, 0xff}
* @param textStyle Flags which specify any styling which should be applied to the rendered string. * @param textStyle Flags which specify any styling which should be applied to the rendered string.
* @return The number of characters printed. * @return The number of characters printed.
*/ */
uint16_t FreeTypeGX::drawText(int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, GXColor color, uint16_t textStyle, uint16_t textWidth, uint16_t widthLimit) uint16_t FreeTypeGX::drawText( int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, GXColor color, uint16_t textStyle, uint16_t textWidth, uint16_t widthLimit )
{ {
if(!text) if ( !text )
return 0; return 0;
uint16_t fullTextWidth = textWidth > 0 ? textWidth : getWidth(text, pixelSize); uint16_t fullTextWidth = textWidth > 0 ? textWidth : getWidth( text, pixelSize );
uint16_t x_pos = x, printed = 0; uint16_t x_pos = x, printed = 0;
uint16_t x_offset = 0, y_offset = 0; uint16_t x_offset = 0, y_offset = 0;
GXTexObj glyphTexture; GXTexObj glyphTexture;
FT_Vector pairDelta; FT_Vector pairDelta;
if(textStyle & FTGX_JUSTIFY_MASK) if ( textStyle & FTGX_JUSTIFY_MASK )
{ {
x_offset = getStyleOffsetWidth(fullTextWidth, textStyle); x_offset = getStyleOffsetWidth( fullTextWidth, textStyle );
} }
if(textStyle & FTGX_ALIGN_MASK) if ( textStyle & FTGX_ALIGN_MASK )
{ {
y_offset = getStyleOffsetHeight(textStyle, pixelSize); y_offset = getStyleOffsetHeight( textStyle, pixelSize );
} }
int i = 0; int i = 0;
while (text[i]) while ( text[i] )
{ {
if(widthLimit > 0 && (x_pos-x) > widthLimit) if ( widthLimit > 0 && ( x_pos - x ) > widthLimit )
break; break;
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize); ftgxCharData* glyphData = cacheGlyphData( text[i], pixelSize );
if (glyphData != NULL) if ( glyphData != NULL )
{ {
if (ftKerningEnabled && i > 0) if ( ftKerningEnabled && i > 0 )
{ {
FT_Get_Kerning(ftFace, fontData[pixelSize][text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); FT_Get_Kerning( ftFace, fontData[pixelSize][text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
x_pos += pairDelta.x >> 6; x_pos += pairDelta.x >> 6;
} }
GX_InitTexObj(&glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE); GX_InitTexObj( &glyphTexture, glyphData->glyphDataTexture, glyphData->textureWidth, glyphData->textureHeight, GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE );
copyTextureToFramebuffer(&glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX + x_offset, y - glyphData->renderOffsetY + y_offset, z, color); copyTextureToFramebuffer( &glyphTexture, glyphData->textureWidth, glyphData->textureHeight, x_pos + glyphData->renderOffsetX + x_offset, y - glyphData->renderOffsetY + y_offset, z, color );
x_pos += glyphData->glyphAdvanceX; x_pos += glyphData->glyphAdvanceX;
++printed; ++printed;
} }
++i; ++i;
} }
if(textStyle & FTGX_STYLE_MASK) if ( textStyle & FTGX_STYLE_MASK )
{ {
getOffset(text, pixelSize, widthLimit); getOffset( text, pixelSize, widthLimit );
drawTextFeature(x + x_offset, y + y_offset, z, pixelSize, fullTextWidth, &ftgxAlign[pixelSize], textStyle, color); drawTextFeature( x + x_offset, y + y_offset, z, pixelSize, fullTextWidth, &ftgxAlign[pixelSize], textStyle, color );
} }
return printed; return printed;
} }
void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, int16_t z, int16_t pixelSize, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color) void FreeTypeGX::drawTextFeature( int16_t x, int16_t y, int16_t z, int16_t pixelSize, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color )
{ {
uint16_t featureHeight = pixelSize >> 4 > 0 ? pixelSize >> 4 : 1; uint16_t featureHeight = pixelSize >> 4 > 0 ? pixelSize >> 4 : 1;
if (format & FTGX_STYLE_UNDERLINE) if ( format & FTGX_STYLE_UNDERLINE )
this->copyFeatureToFramebuffer(width, featureHeight, x, y + 1, z, color); this->copyFeatureToFramebuffer( width, featureHeight, x, y + 1, z, color );
if (format & FTGX_STYLE_STRIKE) if ( format & FTGX_STYLE_STRIKE )
this->copyFeatureToFramebuffer(width, featureHeight, x, y - ((offsetData->max) >> 1), z, color); this->copyFeatureToFramebuffer( width, featureHeight, x, y - ( ( offsetData->max ) >> 1 ), z, color );
} }
/** /**
@ -402,57 +402,57 @@ void FreeTypeGX::drawTextFeature(int16_t x, int16_t y, int16_t z, int16_t pixelS
* This routine processes each character of the supplied text string and calculates the width of the entire string. * This routine processes each character of the supplied text string and calculates the width of the entire string.
* Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.
* *
* @param text NULL terminated string to calculate. * @param text NULL terminated string to calculate.
* @return The width of the text string in pixels. * @return The width of the text string in pixels.
*/ */
uint16_t FreeTypeGX::getWidth(const wchar_t *text, int16_t pixelSize) uint16_t FreeTypeGX::getWidth( const wchar_t *text, int16_t pixelSize )
{ {
if(!text) if ( !text )
return 0; return 0;
uint16_t strWidth = 0; uint16_t strWidth = 0;
FT_Vector pairDelta; FT_Vector pairDelta;
int i = 0; int i = 0;
while (text[i]) while ( text[i] )
{ {
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize); ftgxCharData* glyphData = cacheGlyphData( text[i], pixelSize );
if (glyphData != NULL) if ( glyphData != NULL )
{ {
if (ftKerningEnabled && (i > 0)) if ( ftKerningEnabled && ( i > 0 ) )
{ {
FT_Get_Kerning(ftFace, fontData[pixelSize][text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); FT_Get_Kerning( ftFace, fontData[pixelSize][text[i - 1]].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
strWidth += pairDelta.x >> 6; strWidth += pairDelta.x >> 6;
} }
strWidth += glyphData->glyphAdvanceX; strWidth += glyphData->glyphAdvanceX;
} }
++i; ++i;
} }
return strWidth; return strWidth;
} }
/** /**
* Single char width * Single char width
*/ */
uint16_t FreeTypeGX::getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar) uint16_t FreeTypeGX::getCharWidth( const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar )
{ {
uint16_t strWidth = 0; uint16_t strWidth = 0;
ftgxCharData * glyphData = cacheGlyphData(wChar, pixelSize); ftgxCharData * glyphData = cacheGlyphData( wChar, pixelSize );
if(glyphData != NULL) if ( glyphData != NULL )
{ {
if (ftKerningEnabled && prevChar != 0x0000) if ( ftKerningEnabled && prevChar != 0x0000 )
{ {
FT_Vector pairDelta; FT_Vector pairDelta;
FT_Get_Kerning(ftFace, fontData[pixelSize][prevChar].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta); FT_Get_Kerning( ftFace, fontData[pixelSize][prevChar].glyphIndex, glyphData->glyphIndex, FT_KERNING_DEFAULT, &pairDelta );
strWidth += pairDelta.x >> 6; strWidth += pairDelta.x >> 6;
} }
strWidth += glyphData->glyphAdvanceX; strWidth += glyphData->glyphAdvanceX;
} }
return strWidth; return strWidth;
} }
/** /**
@ -461,14 +461,14 @@ uint16_t FreeTypeGX::getCharWidth(const wchar_t wChar, int16_t pixelSize, const
* This routine processes each character of the supplied text string and calculates the height of the entire string. * This routine processes each character of the supplied text string and calculates the height of the entire string.
* Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function. * Note that if precaching of the entire font set is not enabled any uncached glyph will be cached after the call to this function.
* *
* @param text NULL terminated string to calculate. * @param text NULL terminated string to calculate.
* @return The height of the text string in pixels. * @return The height of the text string in pixels.
*/ */
uint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize) uint16_t FreeTypeGX::getHeight( const wchar_t *text, int16_t pixelSize )
{ {
getOffset(text, pixelSize); getOffset( text, pixelSize );
return ftgxAlign[pixelSize].max - ftgxAlign[pixelSize].min; return ftgxAlign[pixelSize].max - ftgxAlign[pixelSize].min;
} }
/** /**
@ -477,47 +477,47 @@ uint16_t FreeTypeGX::getHeight(const wchar_t *text, int16_t pixelSize)
* This function calculates the maximum pixel height above the font origin line and the minimum * This function calculates the maximum pixel height above the font origin line and the minimum
* pixel height below the font origin line and returns the values in an addressible structure. * pixel height below the font origin line and returns the values in an addressible structure.
* *
* @param text NULL terminated string to calculate. * @param text NULL terminated string to calculate.
* @param offset returns the max and min values above and below the font origin line * @param offset returns the max and min values above and below the font origin line
* *
*/ */
void FreeTypeGX::getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit) void FreeTypeGX::getOffset( const wchar_t *text, int16_t pixelSize, uint16_t widthLimit )
{ {
if(ftgxAlign.find(pixelSize) != ftgxAlign.end()) if ( ftgxAlign.find( pixelSize ) != ftgxAlign.end() )
return; return;
int16_t strMax = 0, strMin = 9999; int16_t strMax = 0, strMin = 9999;
uint16_t currWidth = 0; uint16_t currWidth = 0;
int i = 0; int i = 0;
while (text[i]) while ( text[i] )
{ {
if(widthLimit > 0 && currWidth >= widthLimit) if ( widthLimit > 0 && currWidth >= widthLimit )
break; break;
ftgxCharData* glyphData = cacheGlyphData(text[i], pixelSize); ftgxCharData* glyphData = cacheGlyphData( text[i], pixelSize );
if(glyphData != NULL) if ( glyphData != NULL )
{ {
strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax; strMax = glyphData->renderOffsetMax > strMax ? glyphData->renderOffsetMax : strMax;
strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin; strMin = glyphData->renderOffsetMin < strMin ? glyphData->renderOffsetMin : strMin;
currWidth += glyphData->glyphAdvanceX; currWidth += glyphData->glyphAdvanceX;
} }
++i; ++i;
} }
if(ftPointSize != pixelSize) if ( ftPointSize != pixelSize )
{ {
ftPointSize = pixelSize; ftPointSize = pixelSize;
FT_Set_Pixel_Sizes(ftFace, 0, ftPointSize); FT_Set_Pixel_Sizes( ftFace, 0, ftPointSize );
} }
ftgxAlign[pixelSize].ascender = ftFace->size->metrics.ascender>>6; ftgxAlign[pixelSize].ascender = ftFace->size->metrics.ascender >> 6;
ftgxAlign[pixelSize].descender = ftFace->size->metrics.descender>>6; ftgxAlign[pixelSize].descender = ftFace->size->metrics.descender >> 6;
ftgxAlign[pixelSize].max = strMax; ftgxAlign[pixelSize].max = strMax;
ftgxAlign[pixelSize].min = strMin; ftgxAlign[pixelSize].min = strMin;
} }
/** /**
@ -525,41 +525,41 @@ void FreeTypeGX::getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widt
* *
* This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target. * This routine uses the in-built GX quad builder functions to define the texture bounds and location on the EFB target.
* *
* @param texObj A pointer to the glyph's initialized texture object. * @param texObj A pointer to the glyph's initialized texture object.
* @param texWidth The pixel width of the texture object. * @param texWidth The pixel width of the texture object.
* @param texHeight The pixel height of the texture object. * @param texHeight The pixel height of the texture object.
* @param screenX The screen X coordinate at which to output the rendered texture. * @param screenX The screen X coordinate at which to output the rendered texture.
* @param screenY The screen Y coordinate at which to output the rendered texture. * @param screenY The screen Y coordinate at which to output the rendered texture.
* @param color Color to apply to the texture. * @param color Color to apply to the texture.
*/ */
void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color) void FreeTypeGX::copyTextureToFramebuffer( GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color )
{ {
GX_LoadTexObj(texObj, GX_TEXMAP0); GX_LoadTexObj( texObj, GX_TEXMAP0 );
GX_InvalidateTexAll(); GX_InvalidateTexAll();
GX_SetTevOp (GX_TEVSTAGE0, GX_MODULATE); GX_SetTevOp ( GX_TEVSTAGE0, GX_MODULATE );
GX_SetVtxDesc (GX_VA_TEX0, GX_DIRECT); GX_SetVtxDesc ( GX_VA_TEX0, GX_DIRECT );
GX_Begin(GX_QUADS, this->vertexIndex, 4); GX_Begin( GX_QUADS, this->vertexIndex, 4 );
GX_Position3s16(screenX, screenY, screenZ); GX_Position3s16( screenX, screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_TexCoord2f32(0.0f, 0.0f); GX_TexCoord2f32( 0.0f, 0.0f );
GX_Position3s16(texWidth + screenX, screenY, screenZ); GX_Position3s16( texWidth + screenX, screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_TexCoord2f32(1.0f, 0.0f); GX_TexCoord2f32( 1.0f, 0.0f );
GX_Position3s16(texWidth + screenX, texHeight + screenY, screenZ); GX_Position3s16( texWidth + screenX, texHeight + screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_TexCoord2f32(1.0f, 1.0f); GX_TexCoord2f32( 1.0f, 1.0f );
GX_Position3s16(screenX, texHeight + screenY, screenZ); GX_Position3s16( screenX, texHeight + screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_TexCoord2f32(0.0f, 1.0f); GX_TexCoord2f32( 0.0f, 1.0f );
GX_End(); GX_End();
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); GX_SetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); GX_SetVtxDesc( GX_VA_TEX0, GX_NONE );
} }
/** /**
@ -567,31 +567,31 @@ void FreeTypeGX::copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 te
* *
* This function creates a simple quad for displaying underline or strikeout text styling. * This function creates a simple quad for displaying underline or strikeout text styling.
* *
* @param featureWidth The pixel width of the quad. * @param featureWidth The pixel width of the quad.
* @param featureHeight The pixel height of the quad. * @param featureHeight The pixel height of the quad.
* @param screenX The screen X coordinate at which to output the quad. * @param screenX The screen X coordinate at which to output the quad.
* @param screenY The screen Y coordinate at which to output the quad. * @param screenY The screen Y coordinate at which to output the quad.
* @param color Color to apply to the texture. * @param color Color to apply to the texture.
*/ */
void FreeTypeGX::copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color) void FreeTypeGX::copyFeatureToFramebuffer( f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color )
{ {
GX_SetTevOp (GX_TEVSTAGE0, GX_PASSCLR); GX_SetTevOp ( GX_TEVSTAGE0, GX_PASSCLR );
GX_SetVtxDesc (GX_VA_TEX0, GX_NONE); GX_SetVtxDesc ( GX_VA_TEX0, GX_NONE );
GX_Begin(GX_QUADS, this->vertexIndex, 4); GX_Begin( GX_QUADS, this->vertexIndex, 4 );
GX_Position3s16(screenX, screenY, screenZ); GX_Position3s16( screenX, screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_Position3s16(featureWidth + screenX, screenY, screenZ); GX_Position3s16( featureWidth + screenX, screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_Position3s16(featureWidth + screenX, featureHeight + screenY, screenZ); GX_Position3s16( featureWidth + screenX, featureHeight + screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_Position3s16(screenX, featureHeight + screenY, screenZ); GX_Position3s16( screenX, featureHeight + screenY, screenZ );
GX_Color4u8(color.r, color.g, color.b, color.a); GX_Color4u8( color.r, color.g, color.b, color.a );
GX_End(); GX_End();
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); GX_SetTevOp( GX_TEVSTAGE0, GX_PASSCLR );
GX_SetVtxDesc(GX_VA_TEX0, GX_NONE); GX_SetVtxDesc( GX_VA_TEX0, GX_NONE );
} }

View File

@ -37,30 +37,32 @@
* *
* Font face character glyph relevant data structure. * Font face character glyph relevant data structure.
*/ */
typedef struct ftgxCharData_ { typedef struct ftgxCharData_
int16_t renderOffsetX; /**< Texture X axis bearing offset. */ {
uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */ int16_t renderOffsetX; /**< Texture X axis bearing offset. */
uint32_t glyphIndex; /**< Charachter glyph index in the font face. */ uint16_t glyphAdvanceX; /**< Character glyph X coordinate advance in pixels. */
uint32_t glyphIndex; /**< Charachter glyph index in the font face. */
uint16_t textureWidth; /**< Texture width in pixels/bytes. */ uint16_t textureWidth; /**< Texture width in pixels/bytes. */
uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */ uint16_t textureHeight; /**< Texture glyph height in pixels/bytes. */
int16_t renderOffsetY; /**< Texture Y axis bearing offset. */ int16_t renderOffsetY; /**< Texture Y axis bearing offset. */
int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */ int16_t renderOffsetMax; /**< Texture Y axis bearing maximum value. */
int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */ int16_t renderOffsetMin; /**< Texture Y axis bearing minimum value. */
uint8_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */ uint8_t* glyphDataTexture; /**< Glyph texture bitmap data buffer. */
} ftgxCharData; } ftgxCharData;
/*! \struct ftgxDataOffset_ /*! \struct ftgxDataOffset_
* *
* Offset structure which hold both a maximum and minimum value. * Offset structure which hold both a maximum and minimum value.
*/ */
typedef struct ftgxDataOffset_ { typedef struct ftgxDataOffset_
int16_t ascender; /**< Maximum data offset. */ {
int16_t descender; /**< Minimum data offset. */ int16_t ascender; /**< Maximum data offset. */
int16_t max; /**< Maximum data offset. */ int16_t descender; /**< Minimum data offset. */
int16_t min; /**< Minimum data offset. */ int16_t max; /**< Maximum data offset. */
int16_t min; /**< Minimum data offset. */
} ftgxDataOffset; } ftgxDataOffset;
typedef struct ftgxCharData_ ftgxCharData; typedef struct ftgxCharData_ ftgxCharData;
@ -68,28 +70,28 @@ typedef struct ftgxDataOffset_ ftgxDataOffset;
#define _TEXT(t) L ## t /**< Unicode helper macro. */ #define _TEXT(t) L ## t /**< Unicode helper macro. */
#define FTGX_NULL 0x0000 #define FTGX_NULL 0x0000
#define FTGX_JUSTIFY_LEFT 0x0001 #define FTGX_JUSTIFY_LEFT 0x0001
#define FTGX_JUSTIFY_CENTER 0x0002 #define FTGX_JUSTIFY_CENTER 0x0002
#define FTGX_JUSTIFY_RIGHT 0x0004 #define FTGX_JUSTIFY_RIGHT 0x0004
#define FTGX_JUSTIFY_MASK 0x000f #define FTGX_JUSTIFY_MASK 0x000f
#define FTGX_ALIGN_TOP 0x0010 #define FTGX_ALIGN_TOP 0x0010
#define FTGX_ALIGN_MIDDLE 0x0020 #define FTGX_ALIGN_MIDDLE 0x0020
#define FTGX_ALIGN_BOTTOM 0x0040 #define FTGX_ALIGN_BOTTOM 0x0040
#define FTGX_ALIGN_BASELINE 0x0080 #define FTGX_ALIGN_BASELINE 0x0080
#define FTGX_ALIGN_GLYPH_TOP 0x0100 #define FTGX_ALIGN_GLYPH_TOP 0x0100
#define FTGX_ALIGN_GLYPH_MIDDLE 0x0200 #define FTGX_ALIGN_GLYPH_MIDDLE 0x0200
#define FTGX_ALIGN_GLYPH_BOTTOM 0x0400 #define FTGX_ALIGN_GLYPH_BOTTOM 0x0400
#define FTGX_ALIGN_MASK 0x0ff0 #define FTGX_ALIGN_MASK 0x0ff0
#define FTGX_STYLE_UNDERLINE 0x1000 #define FTGX_STYLE_UNDERLINE 0x1000
#define FTGX_STYLE_STRIKE 0x2000 #define FTGX_STYLE_STRIKE 0x2000
#define FTGX_STYLE_MASK 0xf000 #define FTGX_STYLE_MASK 0xf000
const GXColor ftgxWhite = (GXColor){0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */ const GXColor ftgxWhite = ( GXColor ) {0xff, 0xff, 0xff, 0xff}; /**< Constant color value used only to sanitize Doxygen documentation. */
wchar_t* charToWideChar(const char* p); wchar_t* charToWideChar( const char* p );
/*! \class FreeTypeGX /*! \class FreeTypeGX
* \brief Wrapper class for the libFreeType library with GX rendering. * \brief Wrapper class for the libFreeType library with GX rendering.
@ -102,41 +104,41 @@ wchar_t* charToWideChar(const char* p);
*/ */
class FreeTypeGX class FreeTypeGX
{ {
private: private:
FT_Library ftLibrary; /**< FreeType FT_Library instance. */ FT_Library ftLibrary; /**< FreeType FT_Library instance. */
FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */ FT_Face ftFace; /**< FreeType reusable FT_Face typographic object. */
int16_t ftPointSize; /**< Current set size of the rendered font. */ int16_t ftPointSize; /**< Current set size of the rendered font. */
bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */ bool ftKerningEnabled; /**< Flag indicating the availability of font kerning data. */
uint8_t vertexIndex; /**< Vertex format descriptor index. */ uint8_t vertexIndex; /**< Vertex format descriptor index. */
std::map<int16_t, std::map<wchar_t, ftgxCharData> > fontData; /**< Map which holds the glyph data structures for the corresponding characters in one size. */ std::map<int16_t, std::map<wchar_t, ftgxCharData> > fontData; /**< Map which holds the glyph data structures for the corresponding characters in one size. */
std::map<int16_t, ftgxDataOffset> ftgxAlign; /**< Map which holds the ascender and decender for different sizes. */ std::map<int16_t, ftgxDataOffset> ftgxAlign; /**< Map which holds the ascender and decender for different sizes. */
int16_t getStyleOffsetWidth(uint16_t width, uint16_t format); int16_t getStyleOffsetWidth( uint16_t width, uint16_t format );
int16_t getStyleOffsetHeight(int16_t format, uint16_t pixelSize); int16_t getStyleOffsetHeight( int16_t format, uint16_t pixelSize );
void unloadFont(); void unloadFont();
ftgxCharData *cacheGlyphData(wchar_t charCode, int16_t pixelSize); ftgxCharData *cacheGlyphData( wchar_t charCode, int16_t pixelSize );
uint16_t cacheGlyphDataComplete(int16_t pixelSize); uint16_t cacheGlyphDataComplete( int16_t pixelSize );
void loadGlyphData(FT_Bitmap *bmp, ftgxCharData *charData); void loadGlyphData( FT_Bitmap *bmp, ftgxCharData *charData );
void setDefaultMode(); void setDefaultMode();
void drawTextFeature(int16_t x, int16_t y,int16_t z, int16_t pixelSize, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color); void drawTextFeature( int16_t x, int16_t y, int16_t z, int16_t pixelSize, uint16_t width, ftgxDataOffset *offsetData, uint16_t format, GXColor color );
void copyTextureToFramebuffer(GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color); void copyTextureToFramebuffer( GXTexObj *texObj, f32 texWidth, f32 texHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color );
void copyFeatureToFramebuffer(f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color); void copyFeatureToFramebuffer( f32 featureWidth, f32 featureHeight, int16_t screenX, int16_t screenY, int16_t screenZ, GXColor color );
public: public:
FreeTypeGX(const uint8_t* fontBuffer, FT_Long bufferSize); FreeTypeGX( const uint8_t* fontBuffer, FT_Long bufferSize );
~FreeTypeGX(); ~FreeTypeGX();
void setVertexFormat(uint8_t vertexIndex); void setVertexFormat( uint8_t vertexIndex );
uint16_t drawText(int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL, uint16_t textWidth = 0, uint16_t widthLimit = 0); uint16_t drawText( int16_t x, int16_t y, int16_t z, const wchar_t *text, int16_t pixelSize, GXColor color = ftgxWhite, uint16_t textStyling = FTGX_NULL, uint16_t textWidth = 0, uint16_t widthLimit = 0 );
uint16_t getWidth(const wchar_t *text, int16_t pixelSize); uint16_t getWidth( const wchar_t *text, int16_t pixelSize );
uint16_t getCharWidth(const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000); uint16_t getCharWidth( const wchar_t wChar, int16_t pixelSize, const wchar_t prevChar = 0x0000 );
uint16_t getHeight(const wchar_t *text, int16_t pixelSize); uint16_t getHeight( const wchar_t *text, int16_t pixelSize );
void getOffset(const wchar_t *text, int16_t pixelSize, uint16_t widthLimit = 0); void getOffset( const wchar_t *text, int16_t pixelSize, uint16_t widthLimit = 0 );
}; };
#endif /* FREETYPEGX_H_ */ #endif /* FREETYPEGX_H_ */

View File

@ -39,16 +39,16 @@
#include "ZipFile.h" #include "ZipFile.h"
#include "language/gettext.h" #include "language/gettext.h"
ZipFile::ZipFile(const char *filepath) ZipFile::ZipFile( const char *filepath )
{ {
File = unzOpen(filepath); File = unzOpen( filepath );
if(File) if ( File )
this->LoadList(); this->LoadList();
} }
ZipFile::~ZipFile() ZipFile::~ZipFile()
{ {
unzClose(File); unzClose( File );
} }
bool ZipFile::LoadList() bool ZipFile::LoadList()
@ -56,78 +56,79 @@ bool ZipFile::LoadList()
return true; return true;
} }
bool ZipFile::ExtractAll(const char *dest) bool ZipFile::ExtractAll( const char *dest )
{ {
if(!File) if ( !File )
return false; return false;
bool Stop = false; bool Stop = false;
u32 blocksize = 1024*50; u32 blocksize = 1024 * 50;
u8 *buffer = new u8[blocksize]; u8 *buffer = new u8[blocksize];
if(!buffer) if ( !buffer )
return false; return false;
char writepath[MAXPATHLEN]; char writepath[MAXPATHLEN];
char filename[MAXPATHLEN]; char filename[MAXPATHLEN];
memset(filename, 0, sizeof(filename)); memset( filename, 0, sizeof( filename ) );
int ret = unzGoToFirstFile(File); int ret = unzGoToFirstFile( File );
if(ret != UNZ_OK) if ( ret != UNZ_OK )
Stop = true; Stop = true;
while(!Stop) while ( !Stop )
{ {
if(unzGetCurrentFileInfo(File, &cur_file_info, filename, sizeof(filename), NULL, NULL, NULL, NULL) != UNZ_OK) if ( unzGetCurrentFileInfo( File, &cur_file_info, filename, sizeof( filename ), NULL, NULL, NULL, NULL ) != UNZ_OK )
Stop = true; Stop = true;
if(!Stop && filename[strlen(filename)-1] != '/') if ( !Stop && filename[strlen( filename )-1] != '/' )
{ {
u32 uncompressed_size = cur_file_info.uncompressed_size; u32 uncompressed_size = cur_file_info.uncompressed_size;
u32 done = 0; u32 done = 0;
char *pointer = NULL; char *pointer = NULL;
ret = unzOpenCurrentFile(File); ret = unzOpenCurrentFile( File );
snprintf(writepath, sizeof(writepath), "%s/%s", dest, filename); snprintf( writepath, sizeof( writepath ), "%s/%s", dest, filename );
pointer = strrchr(writepath, '/'); pointer = strrchr( writepath, '/' );
int position = pointer-writepath+2; int position = pointer - writepath + 2;
char temppath[strlen(writepath)]; char temppath[strlen( writepath )];
snprintf(temppath, position, "%s", writepath); snprintf( temppath, position, "%s", writepath );
subfoldercreate(temppath); subfoldercreate( temppath );
if(ret == UNZ_OK) if ( ret == UNZ_OK )
{ {
FILE *pfile = fopen(writepath, "wb"); FILE *pfile = fopen( writepath, "wb" );
do do
{ {
ShowProgress(tr("Extracting files..."), 0, pointer+1, done, uncompressed_size); ShowProgress( tr( "Extracting files..." ), 0, pointer + 1, done, uncompressed_size );
if(uncompressed_size - done < blocksize) if ( uncompressed_size - done < blocksize )
blocksize = uncompressed_size - done; blocksize = uncompressed_size - done;
ret = unzReadCurrentFile(File, buffer, blocksize); ret = unzReadCurrentFile( File, buffer, blocksize );
if(ret == 0) if ( ret == 0 )
break; break;
fwrite(buffer, 1, blocksize, pfile); fwrite( buffer, 1, blocksize, pfile );
done += ret; done += ret;
} while(done < uncompressed_size); }
while ( done < uncompressed_size );
fclose(pfile); fclose( pfile );
unzCloseCurrentFile(File); unzCloseCurrentFile( File );
} }
} }
if(unzGoToNextFile(File) != UNZ_OK) if ( unzGoToNextFile( File ) != UNZ_OK )
Stop = true; Stop = true;
} }

View File

@ -32,22 +32,22 @@
typedef struct typedef struct
{ {
u64 offset; // ZipFile offset u64 offset; // ZipFile offset
u64 length; // uncompressed file length in 64 bytes for sizes higher than 4GB u64 length; // uncompressed file length in 64 bytes for sizes higher than 4GB
bool isdir; // 0 - file, 1 - directory bool isdir; // 0 - file, 1 - directory
char filename[256]; // full filename char filename[256]; // full filename
} FileStructure; } FileStructure;
class ZipFile class ZipFile
{ {
public: public:
//!Constructor //!Constructor
ZipFile(const char *filepath); ZipFile( const char *filepath );
//!Destructor //!Destructor
~ZipFile(); ~ZipFile();
//!Extract all files from a zip file to a directory //!Extract all files from a zip file to a directory
//!\param dest Destination path to where to extract //!\param dest Destination path to where to extract
bool ExtractAll(const char *dest); bool ExtractAll( const char *dest );
protected: protected:
bool LoadList(); bool LoadList();
unzFile File; unzFile File;

View File

@ -15,10 +15,11 @@
* *
* Initializes the Wii's audio subsystem * Initializes the Wii's audio subsystem
***************************************************************************/ ***************************************************************************/
void InitAudio() { void InitAudio()
AUDIO_Init(NULL); {
AUDIO_Init( NULL );
ASND_Init(); ASND_Init();
ASND_Pause(0); ASND_Pause( 0 );
} }
/**************************************************************************** /****************************************************************************
@ -27,7 +28,8 @@ void InitAudio() {
* Shuts down audio subsystem. Useful to avoid unpleasant sounds if a * Shuts down audio subsystem. Useful to avoid unpleasant sounds if a
* crash occurs during shutdown. * crash occurs during shutdown.
***************************************************************************/ ***************************************************************************/
void ShutdownAudio() { void ShutdownAudio()
ASND_Pause(1); {
ASND_Pause( 1 );
ASND_End(); ASND_End();
} }

View File

@ -7,10 +7,10 @@
* *
* Email: crh@ubiqx.mn.org * Email: crh@ubiqx.mn.org
* *
* $Id: MD5.c,v 0.6 2005/06/08 18:35:59 crh Exp $ * $Id: MD5.c,v 0.6 2005/06/08 18:35:59 crh Exp $
* *
* *
* Modifications and additions by dimok * Modifications and additions by dimok
* *
* -------------------------------------------------------------------------- ** * -------------------------------------------------------------------------- **
* *
@ -75,14 +75,14 @@
* *
* ========================================================================== ** * ========================================================================== **
*/ */
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <ctype.h> #include <ctype.h>
#include "MD5.h" #include "MD5.h"
@ -111,28 +111,28 @@
*/ */
static const uint8_t K[3][16] = static const uint8_t K[3][16] =
{ {
/* Round 1: skipped (since it is simply sequential). */ /* Round 1: skipped (since it is simply sequential). */
{ 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 }, /* R2 */ { 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12 }, /* R2 */
{ 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 }, /* R3 */ { 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2 }, /* R3 */
{ 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 } /* R4 */ { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 } /* R4 */
}; };
static const uint8_t S[4][4] = static const uint8_t S[4][4] =
{ {
{ 7, 12, 17, 22 }, /* Round 1 */ { 7, 12, 17, 22 }, /* Round 1 */
{ 5, 9, 14, 20 }, /* Round 2 */ { 5, 9, 14, 20 }, /* Round 2 */
{ 4, 11, 16, 23 }, /* Round 3 */ { 4, 11, 16, 23 }, /* Round 3 */
{ 6, 10, 15, 21 } /* Round 4 */ { 6, 10, 15, 21 } /* Round 4 */
}; };
static const uint32_t T[4][16] = static const uint32_t T[4][16] =
{ {
{ 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */ { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, /* Round 1 */
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 }, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 },
{ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */ { 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, /* Round 2 */
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
@ -148,7 +148,7 @@ static const uint32_t T[4][16] =
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 },
}; };
/* -------------------------------------------------------------------------- ** /* -------------------------------------------------------------------------- **
@ -168,8 +168,8 @@ static const uint32_t T[4][16] =
#define md5H( X, Y, Z ) ( (X) ^ (Y) ^ (Z) ) #define md5H( X, Y, Z ) ( (X) ^ (Y) ^ (Z) )
#define md5I( X, Y, Z ) ( (Y) ^ ((X) | (~(Z))) ) #define md5I( X, Y, Z ) ( (Y) ^ ((X) | (~(Z))) )
#define GetLongByte( L, idx ) ((unsigned char)(( L >> (((idx) & 0x03) << 3) ) & 0xFF)) #define GetLongByte( L, idx ) ((unsigned char)(( L >> (((idx) & 0x03) << 3) ) & 0xFF))
#define STR2HEX(x) ((x >= 0x30) && (x <= 0x39)) ? x - 0x30 : toupper((int)x)-0x37 #define STR2HEX(x) ((x >= 0x30) && (x <= 0x39)) ? x - 0x30 : toupper((int)x)-0x37
@ -178,122 +178,122 @@ static const uint32_t T[4][16] =
*/ */
static void Permute( uint32_t ABCD[4], const unsigned char block[64] ) static void Permute( uint32_t ABCD[4], const unsigned char block[64] )
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Permute the ABCD "registers" using the 64-byte <block> as a driver. * Permute the ABCD "registers" using the 64-byte <block> as a driver.
* *
* Input: ABCD - Pointer to an array of four unsigned longwords. * Input: ABCD - Pointer to an array of four unsigned longwords.
* block - An array of bytes, 64 bytes in size. * block - An array of bytes, 64 bytes in size.
* *
* Output: none. * Output: none.
* *
* Notes: The MD5 algorithm operates on a set of four longwords stored * Notes: The MD5 algorithm operates on a set of four longwords stored
* (conceptually) in four "registers". It is easy to imagine a * (conceptually) in four "registers". It is easy to imagine a
* simple MD4/5 chip that would operate this way. In any case, * simple MD4/5 chip that would operate this way. In any case,
* the mangling of the contents of those registers is driven by * the mangling of the contents of those registers is driven by
* the input message. The message is chopped and finally padded * the input message. The message is chopped and finally padded
* into 64-byte chunks and each chunk is used to manipulate the * into 64-byte chunks and each chunk is used to manipulate the
* contents of the registers. * contents of the registers.
* *
* The MD5 Algorithm calls for padding the input to ensure that * The MD5 Algorithm calls for padding the input to ensure that
* it is a multiple of 64 bytes in length. The last 16 bytes * it is a multiple of 64 bytes in length. The last 16 bytes
* of the padding space are used to store the message length * of the padding space are used to store the message length
* (the length of the original message, before padding, expressed * (the length of the original message, before padding, expressed
* in terms of bits). If there is not enough room for 16 bytes * in terms of bits). If there is not enough room for 16 bytes
* worth of bitcount (eg., if the original message was 122 bytes * worth of bitcount (eg., if the original message was 122 bytes
* long) then the block is padded to the end with zeros and * long) then the block is padded to the end with zeros and
* passed to this function. Then *another* block is filled with * passed to this function. Then *another* block is filled with
* zeros except for the last 16 bytes which contain the length. * zeros except for the last 16 bytes which contain the length.
* *
* Oh... and the algorithm requires that there be at least one * Oh... and the algorithm requires that there be at least one
* padding byte. The first padding byte has a value of 0x80, * padding byte. The first padding byte has a value of 0x80,
* and any others are 0x00. * and any others are 0x00.
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
{ {
int round; int round;
int i, j; int i, j;
uint8_t s; uint8_t s;
uint32_t a, b, c, d; uint32_t a, b, c, d;
uint32_t KeepABCD[4]; uint32_t KeepABCD[4];
uint32_t X[16]; uint32_t X[16];
/* Store the current ABCD values for later re-use. /* Store the current ABCD values for later re-use.
*/ */
for( i = 0; i < 4; i++ ) for ( i = 0; i < 4; i++ )
KeepABCD[i] = ABCD[i]; KeepABCD[i] = ABCD[i];
/* Convert the input block into an array of unsigned longs, taking care /* Convert the input block into an array of unsigned longs, taking care
* to read the block in Little Endian order (the algorithm assumes this). * to read the block in Little Endian order (the algorithm assumes this).
* The uint32_t values are then handled in host order. * The uint32_t values are then handled in host order.
*/ */
for( i = 0, j = 0; i < 16; i++ ) for ( i = 0, j = 0; i < 16; i++ )
{ {
X[i] = (uint32_t)block[j++]; X[i] = ( uint32_t )block[j++];
X[i] |= ((uint32_t)block[j++] << 8); X[i] |= ( ( uint32_t )block[j++] << 8 );
X[i] |= ((uint32_t)block[j++] << 16); X[i] |= ( ( uint32_t )block[j++] << 16 );
X[i] |= ((uint32_t)block[j++] << 24); X[i] |= ( ( uint32_t )block[j++] << 24 );
} }
/* This loop performs the four rounds of permutations. /* This loop performs the four rounds of permutations.
* The rounds are each very similar. The differences are in three areas: * The rounds are each very similar. The differences are in three areas:
* - The function (F, G, H, or I) used to perform bitwise permutations * - The function (F, G, H, or I) used to perform bitwise permutations
* on the registers, * on the registers,
* - The order in which values from X[] are chosen. * - The order in which values from X[] are chosen.
* - Changes to the number of bits by which the registers are rotated. * - Changes to the number of bits by which the registers are rotated.
* This implementation uses a switch statement to deal with some of the * This implementation uses a switch statement to deal with some of the
* differences between rounds. Other differences are handled by storing * differences between rounds. Other differences are handled by storing
* values in arrays and using the round number to select the correct set * values in arrays and using the round number to select the correct set
* of values. * of values.
* *
* (My implementation appears to be a poor compromise between speed, size, * (My implementation appears to be a poor compromise between speed, size,
* and clarity. Ugh. [crh]) * and clarity. Ugh. [crh])
*/ */
for( round = 0; round < 4; round++ ) for ( round = 0; round < 4; round++ )
{ {
for( i = 0; i < 16; i++ ) for ( i = 0; i < 16; i++ )
{
j = (4 - (i % 4)) & 0x3; /* <j> handles the rotation of ABCD. */
s = S[round][i%4]; /* <s> is the bit shift for this iteration. */
b = ABCD[(j+1) & 0x3]; /* Copy the b,c,d values per ABCD rotation. */
c = ABCD[(j+2) & 0x3]; /* This isn't really necessary, it just looks */
d = ABCD[(j+3) & 0x3]; /* clean & will hopefully be optimized away. */
/* The actual perumation function.
* This is broken out to minimize the code within the switch().
*/
switch( round )
{ {
case 0: j = ( 4 - ( i % 4 ) ) & 0x3; /* <j> handles the rotation of ABCD. */
/* round 1 */ s = S[round][i%4]; /* <s> is the bit shift for this iteration. */
a = md5F( b, c, d ) + X[i];
break; b = ABCD[( j+1 ) & 0x3]; /* Copy the b,c,d values per ABCD rotation. */
case 1: c = ABCD[( j+2 ) & 0x3]; /* This isn't really necessary, it just looks */
/* round 2 */ d = ABCD[( j+3 ) & 0x3]; /* clean & will hopefully be optimized away. */
a = md5G( b, c, d ) + X[ K[0][i] ];
break; /* The actual perumation function.
case 2: * This is broken out to minimize the code within the switch().
/* round 3 */ */
a = md5H( b, c, d ) + X[ K[1][i] ]; switch ( round )
break; {
default: case 0:
/* round 4 */ /* round 1 */
a = md5I( b, c, d ) + X[ K[2][i] ]; a = md5F( b, c, d ) + X[i];
break; break;
case 1:
/* round 2 */
a = md5G( b, c, d ) + X[ K[0][i] ];
break;
case 2:
/* round 3 */
a = md5H( b, c, d ) + X[ K[1][i] ];
break;
default:
/* round 4 */
a = md5I( b, c, d ) + X[ K[2][i] ];
break;
}
a = 0xFFFFFFFF & ( ABCD[j] + a + T[round][i] );
ABCD[j] = b + ( 0xFFFFFFFF & ( ( a << s ) | ( a >> ( 32 - s ) ) ) );
} }
a = 0xFFFFFFFF & ( ABCD[j] + a + T[round][i] );
ABCD[j] = b + (0xFFFFFFFF & (( a << s ) | ( a >> (32 - s) )));
}
} }
/* Use the stored original A, B, C, D values to perform /* Use the stored original A, B, C, D values to perform
* one last convolution. * one last convolution.
*/ */
for( i = 0; i < 4; i++ ) for ( i = 0; i < 4; i++ )
ABCD[i] = 0xFFFFFFFF & ( ABCD[i] + KeepABCD[i] ); ABCD[i] = 0xFFFFFFFF & ( ABCD[i] + KeepABCD[i] );
} /* Permute */ } /* Permute */
/* -------------------------------------------------------------------------- ** /* -------------------------------------------------------------------------- **
@ -301,330 +301,333 @@ static void Permute( uint32_t ABCD[4], const unsigned char block[64] )
*/ */
auth_md5Ctx *auth_md5InitCtx( auth_md5Ctx *ctx ) auth_md5Ctx *auth_md5InitCtx( auth_md5Ctx *ctx )
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Initialize an MD5 context. * Initialize an MD5 context.
* *
* Input: ctx - A pointer to the MD5 context structure to be initialized. * Input: ctx - A pointer to the MD5 context structure to be initialized.
* Contexts are typically created thusly: * Contexts are typically created thusly:
* ctx = (auth_md5Ctx *)malloc( sizeof(auth_md5Ctx) ); * ctx = (auth_md5Ctx *)malloc( sizeof(auth_md5Ctx) );
* *
* Output: A pointer to the initialized context (same as <ctx>). * Output: A pointer to the initialized context (same as <ctx>).
* *
* Notes: The purpose of the context is to make it possible to generate * Notes: The purpose of the context is to make it possible to generate
* an MD5 Message Digest in stages, rather than having to pass a * an MD5 Message Digest in stages, rather than having to pass a
* single large block to a single MD5 function. The context * single large block to a single MD5 function. The context
* structure keeps track of various bits of state information. * structure keeps track of various bits of state information.
* *
* Once the context is initialized, the blocks of message data * Once the context is initialized, the blocks of message data
* are passed to the <auth_md5SumCtx()> function. Once the * are passed to the <auth_md5SumCtx()> function. Once the
* final bit of data has been handed to <auth_md5SumCtx()> the * final bit of data has been handed to <auth_md5SumCtx()> the
* context can be closed out by calling <auth_md5CloseCtx()>, * context can be closed out by calling <auth_md5CloseCtx()>,
* which also calculates the final MD5 result. * which also calculates the final MD5 result.
* *
* Don't forget to free an allocated context structure when * Don't forget to free an allocated context structure when
* you've finished using it. * you've finished using it.
* *
* See Also: <auth_md5SumCtx()>, <auth_md5CloseCtx()> * See Also: <auth_md5SumCtx()>, <auth_md5CloseCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
{ {
ctx->len = 0; ctx->len = 0;
ctx->b_used = 0; ctx->b_used = 0;
ctx->ABCD[0] = 0x67452301; /* The array ABCD[] contains the four 4-byte */ ctx->ABCD[0] = 0x67452301; /* The array ABCD[] contains the four 4-byte */
ctx->ABCD[1] = 0xefcdab89; /* "registers" that are manipulated to */ ctx->ABCD[1] = 0xefcdab89; /* "registers" that are manipulated to */
ctx->ABCD[2] = 0x98badcfe; /* produce the MD5 digest. The input acts */ ctx->ABCD[2] = 0x98badcfe; /* produce the MD5 digest. The input acts */
ctx->ABCD[3] = 0x10325476; /* upon the registers, not the other way */ ctx->ABCD[3] = 0x10325476; /* upon the registers, not the other way */
/* 'round. The initial values are those */ /* 'round. The initial values are those */
/* given in RFC 1321 (pg. 4). Note, however, that RFC 1321 */ /* given in RFC 1321 (pg. 4). Note, however, that RFC 1321 */
/* provides these values as bytes, not as longwords, and the */ /* provides these values as bytes, not as longwords, and the */
/* bytes are arranged in little-endian order as if they were */ /* bytes are arranged in little-endian order as if they were */
/* the bytes of (little endian) 32-bit ints. That's */ /* the bytes of (little endian) 32-bit ints. That's */
/* confusing as all getout (to me, anyway). The values given */ /* confusing as all getout (to me, anyway). The values given */
/* here are provided as 32-bit values in C language format, */ /* here are provided as 32-bit values in C language format, */
/* so they are endian-agnostic. */ /* so they are endian-agnostic. */
return( ctx ); return( ctx );
} /* auth_md5InitCtx */ } /* auth_md5InitCtx */
auth_md5Ctx *auth_md5SumCtx( auth_md5Ctx *ctx, auth_md5Ctx *auth_md5SumCtx( auth_md5Ctx *ctx,
const unsigned char *src, const unsigned char *src,
const int len ) const int len )
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Build an MD5 Message Digest within the given context. * Build an MD5 Message Digest within the given context.
* *
* Input: ctx - Pointer to the context in which the MD5 sum is being * Input: ctx - Pointer to the context in which the MD5 sum is being
* built. * built.
* src - A chunk of source data. This will be used to drive * src - A chunk of source data. This will be used to drive
* the MD5 algorithm. * the MD5 algorithm.
* len - The number of bytes in <src>. * len - The number of bytes in <src>.
* *
* Output: A pointer to the updated context (same as <ctx>). * Output: A pointer to the updated context (same as <ctx>).
* *
* See Also: <auth_md5InitCtx()>, <auth_md5CloseCtx()>, <auth_md5Sum()> * See Also: <auth_md5InitCtx()>, <auth_md5CloseCtx()>, <auth_md5Sum()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
{ {
int i; int i;
/* Add the new block's length to the total length. /* Add the new block's length to the total length.
*/ */
ctx->len += (uint32_t)len; ctx->len += ( uint32_t )len;
/* Copy the new block's data into the context block. /* Copy the new block's data into the context block.
* Call the Permute() function whenever the context block is full. * Call the Permute() function whenever the context block is full.
*/ */
for( i = 0; i < len; i++ ) for ( i = 0; i < len; i++ )
{ {
ctx->block[ ctx->b_used ] = src[i]; ctx->block[ ctx->b_used ] = src[i];
(ctx->b_used)++; ( ctx->b_used )++;
if( 64 == ctx->b_used ) if ( 64 == ctx->b_used )
{ {
Permute( ctx->ABCD, ctx->block ); Permute( ctx->ABCD, ctx->block );
ctx->b_used = 0; ctx->b_used = 0;
} }
} }
/* Return the updated context. /* Return the updated context.
*/ */
return( ctx ); return( ctx );
} /* auth_md5SumCtx */ } /* auth_md5SumCtx */
auth_md5Ctx *auth_md5CloseCtx( auth_md5Ctx *ctx, unsigned char *dst ) auth_md5Ctx *auth_md5CloseCtx( auth_md5Ctx *ctx, unsigned char *dst )
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Close an MD5 Message Digest context and generate the final MD5 sum. * Close an MD5 Message Digest context and generate the final MD5 sum.
* *
* Input: ctx - Pointer to the context in which the MD5 sum is being * Input: ctx - Pointer to the context in which the MD5 sum is being
* built. * built.
* dst - A pointer to at least 16 bytes of memory, which will * dst - A pointer to at least 16 bytes of memory, which will
* receive the finished MD5 sum. * receive the finished MD5 sum.
* *
* Output: A pointer to the closed context (same as <ctx>). * Output: A pointer to the closed context (same as <ctx>).
* You might use this to free a malloc'd context structure. :) * You might use this to free a malloc'd context structure. :)
* *
* Notes: The context (<ctx>) is returned in an undefined state. * Notes: The context (<ctx>) is returned in an undefined state.
* It must be re-initialized before re-use. * It must be re-initialized before re-use.
* *
* See Also: <auth_md5InitCtx()>, <auth_md5SumCtx()> * See Also: <auth_md5InitCtx()>, <auth_md5SumCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
{ {
int i; int i;
uint32_t l; uint32_t l;
/* Add the required 0x80 padding initiator byte. /* Add the required 0x80 padding initiator byte.
* The auth_md5SumCtx() function always permutes and resets the context * The auth_md5SumCtx() function always permutes and resets the context
* block when it gets full, so we know that there must be at least one * block when it gets full, so we know that there must be at least one
* free byte in the context block. * free byte in the context block.
*/ */
ctx->block[ctx->b_used] = 0x80; ctx->block[ctx->b_used] = 0x80;
(ctx->b_used)++; ( ctx->b_used )++;
/* Zero out any remaining free bytes in the context block. /* Zero out any remaining free bytes in the context block.
*/ */
for( i = ctx->b_used; i < 64; i++ ) for ( i = ctx->b_used; i < 64; i++ )
ctx->block[i] = 0; ctx->block[i] = 0;
/* We need 8 bytes to store the length field. /* We need 8 bytes to store the length field.
* If we don't have 8, call Permute() and reset the context block. * If we don't have 8, call Permute() and reset the context block.
*/ */
if( 56 < ctx->b_used ) if ( 56 < ctx->b_used )
{ {
Permute( ctx->ABCD, ctx->block );
for ( i = 0; i < 64; i++ )
ctx->block[i] = 0;
}
/* Add the total length and perform the final perumation.
* Note: The 60'th byte is read from the *original* <ctx->len> value
* and shifted to the correct position. This neatly avoids
* any MAXINT numeric overflow issues.
*/
l = ctx->len << 3;
for ( i = 0; i < 4; i++ )
ctx->block[56+i] |= GetLongByte( l, i );
ctx->block[60] = ( ( GetLongByte( ctx->len, 3 ) & 0xE0 ) >> 5 ); /* See Above! */
Permute( ctx->ABCD, ctx->block ); Permute( ctx->ABCD, ctx->block );
for( i = 0; i < 64; i++ )
ctx->block[i] = 0;
}
/* Add the total length and perform the final perumation. /* Now copy the result into the output buffer and we're done.
* Note: The 60'th byte is read from the *original* <ctx->len> value */
* and shifted to the correct position. This neatly avoids for ( i = 0; i < 4; i++ )
* any MAXINT numeric overflow issues.
*/
l = ctx->len << 3;
for( i = 0; i < 4; i++ )
ctx->block[56+i] |= GetLongByte( l, i );
ctx->block[60] = ((GetLongByte( ctx->len, 3 ) & 0xE0) >> 5); /* See Above! */
Permute( ctx->ABCD, ctx->block );
/* Now copy the result into the output buffer and we're done.
*/
for( i = 0; i < 4; i++ )
{ {
dst[ 0+i] = GetLongByte( ctx->ABCD[0], i ); dst[ 0+i] = GetLongByte( ctx->ABCD[0], i );
dst[ 4+i] = GetLongByte( ctx->ABCD[1], i ); dst[ 4+i] = GetLongByte( ctx->ABCD[1], i );
dst[ 8+i] = GetLongByte( ctx->ABCD[2], i ); dst[ 8+i] = GetLongByte( ctx->ABCD[2], i );
dst[12+i] = GetLongByte( ctx->ABCD[3], i ); dst[12+i] = GetLongByte( ctx->ABCD[3], i );
} }
/* Return the context. /* Return the context.
* This is done for compatibility with the other auth_md5*Ctx() functions. * This is done for compatibility with the other auth_md5*Ctx() functions.
*/ */
return( ctx ); return( ctx );
} /* auth_md5CloseCtx */ } /* auth_md5CloseCtx */
unsigned char * MD5(unsigned char *dst, const unsigned char *src, const int len ) unsigned char * MD5( unsigned char *dst, const unsigned char *src, const int len )
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Compute an MD5 message digest. * Compute an MD5 message digest.
* *
* Input: dst - Destination buffer into which the result will be written. * Input: dst - Destination buffer into which the result will be written.
* Must be 16 bytes, minimum. * Must be 16 bytes, minimum.
* src - Source data block to be MD5'd. * src - Source data block to be MD5'd.
* len - The length, in bytes, of the source block. * len - The length, in bytes, of the source block.
* (Note that the length is given in bytes, not bits.) * (Note that the length is given in bytes, not bits.)
* *
* Output: A pointer to <dst>, which will contain the calculated 16-byte * Output: A pointer to <dst>, which will contain the calculated 16-byte
* MD5 message digest. * MD5 message digest.
* *
* Notes: This function is a shortcut. It takes a single input block. * Notes: This function is a shortcut. It takes a single input block.
* For more drawn-out operations, see <auth_md5InitCtx()>. * For more drawn-out operations, see <auth_md5InitCtx()>.
* *
* This function is interface-compatible with the * This function is interface-compatible with the
* <auth_md4Sum()> function in the MD4 module. * <auth_md4Sum()> function in the MD4 module.
* *
* The MD5 algorithm is designed to work on data with an * The MD5 algorithm is designed to work on data with an
* arbitrary *bit* length. Most implementations, this one * arbitrary *bit* length. Most implementations, this one
* included, handle the input data in byte-sized chunks. * included, handle the input data in byte-sized chunks.
* *
* The MD5 algorithm does much of its work using four-byte * The MD5 algorithm does much of its work using four-byte
* words, and so can be tuned for speed based on the endian-ness * words, and so can be tuned for speed based on the endian-ness
* of the host. This implementation is intended to be * of the host. This implementation is intended to be
* endian-neutral, which may make it a teeny bit slower than * endian-neutral, which may make it a teeny bit slower than
* others. ...maybe. * others. ...maybe.
* *
* See Also: <auth_md5InitCtx()> * See Also: <auth_md5InitCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
{ {
auth_md5Ctx ctx[1]; auth_md5Ctx ctx[1];
(void)auth_md5InitCtx( ctx ); /* Open a context. */ ( void )auth_md5InitCtx( ctx ); /* Open a context. */
(void)auth_md5SumCtx( ctx, src, len ); /* Pass only one block. */ ( void )auth_md5SumCtx( ctx, src, len ); /* Pass only one block. */
(void)auth_md5CloseCtx( ctx, dst ); /* Close the context. */ ( void )auth_md5CloseCtx( ctx, dst ); /* Close the context. */
return( dst ); /* Makes life easy. */ return( dst ); /* Makes life easy. */
} /* auth_md5Sum */ } /* auth_md5Sum */
unsigned char * MD5fromFile(unsigned char *dst, const char *src)
/* ------------------------------------------------------------------------ **
* Compute an MD5 message digest.
*
* Input: dst - Destination buffer into which the result will be written.
* Must be 16 bytes, minimum.
* src - filepath of the file to be checked
*
* Output: A pointer to <dst>, which will contain the calculated 16-byte
* MD5 message digest.
*
* Notes: This function is a shortcut. It takes a single input block.
* For more drawn-out operations, see <auth_md5InitCtx()>.
*
* This function is interface-compatible with the
* <auth_md4Sum()> function in the MD4 module.
*
* The MD5 algorithm is designed to work on data with an
* arbitrary *bit* length. Most implementations, this one
* included, handle the input data in byte-sized chunks.
*
* The MD5 algorithm does much of its work using four-byte
* words, and so can be tuned for speed based on the endian-ness
* of the host. This implementation is intended to be
* endian-neutral, which may make it a teeny bit slower than
* others. ...maybe.
*
* See Also: <auth_md5InitCtx()>
*
* ------------------------------------------------------------------------ **
*/
{
auth_md5Ctx ctx[1];
FILE * file;
unsigned int blksize = 0;
unsigned int read = 0;
file = fopen(src, "rb");
if (file==NULL){
unsigned char * MD5fromFile( unsigned char *dst, const char *src )
/* ------------------------------------------------------------------------ **
* Compute an MD5 message digest.
*
* Input: dst - Destination buffer into which the result will be written.
* Must be 16 bytes, minimum.
* src - filepath of the file to be checked
*
* Output: A pointer to <dst>, which will contain the calculated 16-byte
* MD5 message digest.
*
* Notes: This function is a shortcut. It takes a single input block.
* For more drawn-out operations, see <auth_md5InitCtx()>.
*
* This function is interface-compatible with the
* <auth_md4Sum()> function in the MD4 module.
*
* The MD5 algorithm is designed to work on data with an
* arbitrary *bit* length. Most implementations, this one
* included, handle the input data in byte-sized chunks.
*
* The MD5 algorithm does much of its work using four-byte
* words, and so can be tuned for speed based on the endian-ness
* of the host. This implementation is intended to be
* endian-neutral, which may make it a teeny bit slower than
* others. ...maybe.
*
* See Also: <auth_md5InitCtx()>
*
* ------------------------------------------------------------------------ **
*/
{
auth_md5Ctx ctx[1];
FILE * file;
unsigned int blksize = 0;
unsigned int read = 0;
file = fopen( src, "rb" );
if ( file == NULL )
{
return NULL; return NULL;
} }
(void)auth_md5InitCtx( ctx ); /* Open a context. */ ( void )auth_md5InitCtx( ctx ); /* Open a context. */
fseek (file , 0 , SEEK_END);
unsigned long long filesize = ftell(file);
rewind (file);
if(filesize < 1048576) //1MB cache for files bigger than 1 MB
blksize = filesize;
else
blksize = 1048576;
unsigned char * buffer = malloc(blksize);
if(buffer == NULL){
//no memory
fclose(file);
return NULL;
}
do
{
read = fread(buffer, 1, blksize, file);
(void)auth_md5SumCtx( ctx, buffer, read ); /* Pass only one block. */
} while(read > 0);
fclose(file);
free(buffer);
(void)auth_md5CloseCtx( ctx, dst ); /* Close the context. */ fseek ( file , 0 , SEEK_END );
unsigned long long filesize = ftell( file );
rewind ( file );
if ( filesize < 1048576 ) //1MB cache for files bigger than 1 MB
blksize = filesize;
else
blksize = 1048576;
unsigned char * buffer = malloc( blksize );
if ( buffer == NULL )
{
//no memory
fclose( file );
return NULL;
}
do
{
read = fread( buffer, 1, blksize, file );
( void )auth_md5SumCtx( ctx, buffer, read ); /* Pass only one block. */
}
while ( read > 0 );
fclose( file );
free( buffer );
( void )auth_md5CloseCtx( ctx, dst ); /* Close the context. */
return( dst ); /* Makes life easy. */ return( dst ); /* Makes life easy. */
} /* auth_md5Sum */ } /* auth_md5Sum */
const char * MD5ToString(const unsigned char * hash, char * dst) const char * MD5ToString( const unsigned char * hash, char * dst )
{ {
char hexchar[3]; char hexchar[3];
short i = 0, n = 0; short i = 0, n = 0;
for (i = 0; i < 16; i++) for ( i = 0; i < 16; i++ )
{ {
sprintf(hexchar, "%02X", hash[i]); sprintf( hexchar, "%02X", hash[i] );
dst[n++] = hexchar[0]; dst[n++] = hexchar[0];
dst[n++] = hexchar[1]; dst[n++] = hexchar[1];
} }
dst[n] = 0x00; dst[n] = 0x00;
return dst; return dst;
} }
unsigned char * StringToMD5(const char * hash, unsigned char * dst) unsigned char * StringToMD5( const char * hash, unsigned char * dst )
{ {
char hexchar[2]; char hexchar[2];
short i = 0, n = 0; short i = 0, n = 0;
for (i = 0; i < 16; i++) for ( i = 0; i < 16; i++ )
{ {
hexchar[0] = hash[n++]; hexchar[0] = hash[n++];
hexchar[1] = hash[n++]; hexchar[1] = hash[n++];
dst[i] = STR2HEX(hexchar[0]); dst[i] = STR2HEX( hexchar[0] );
dst[i] <<= 4; dst[i] <<= 4;
dst[i] += STR2HEX(hexchar[1]); dst[i] += STR2HEX( hexchar[1] );
} }
return dst; return dst;
} }

View File

@ -1,246 +1,246 @@
#ifndef MD5_H #ifndef MD5_H
#define MD5_H #define MD5_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"
{ {
#endif #endif
/* ========================================================================== ** /* ========================================================================== **
* *
* MD5.h * MD5.h
* *
* Copyright: * Copyright:
* Copyright (C) 2003-2005 by Christopher R. Hertel * Copyright (C) 2003-2005 by Christopher R. Hertel
* *
* Email: crh@ubiqx.mn.org * Email: crh@ubiqx.mn.org
* *
* $Id: MD5.h,v 0.6 2005/06/08 18:35:59 crh Exp $ * $Id: MD5.h,v 0.6 2005/06/08 18:35:59 crh Exp $
* *
* Modifications and additions by dimok * Modifications and additions by dimok
* *
* -------------------------------------------------------------------------- ** * -------------------------------------------------------------------------- **
* *
* Description: * Description:
* Implements the MD5 hash algorithm, as described in RFC 1321. * Implements the MD5 hash algorithm, as described in RFC 1321.
* *
* -------------------------------------------------------------------------- ** * -------------------------------------------------------------------------- **
* *
* License: * License:
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version. * version 2.1 of the License, or (at your option) any later version.
* *
* This library is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public * You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* *
* -------------------------------------------------------------------------- ** * -------------------------------------------------------------------------- **
* *
* Notes: * Notes:
* *
* None of this will make any sense unless you're studying RFC 1321 as you * None of this will make any sense unless you're studying RFC 1321 as you
* read the code. * read the code.
* *
* MD5 is described in RFC 1321. * MD5 is described in RFC 1321.
* The MD*4* algorithm is described in RFC 1320 (that's 1321 - 1). * The MD*4* algorithm is described in RFC 1320 (that's 1321 - 1).
* MD5 is very similar to MD4, but not quite similar enough to justify * MD5 is very similar to MD4, but not quite similar enough to justify
* putting the two into a single module. Besides, I wanted to add a few * putting the two into a single module. Besides, I wanted to add a few
* extra functions to this one to expand its usability. * extra functions to this one to expand its usability.
* *
* There are three primary motivations for this particular implementation. * There are three primary motivations for this particular implementation.
* 1) Programmer's pride. I wanted to be able to say I'd done it, and I * 1) Programmer's pride. I wanted to be able to say I'd done it, and I
* wanted to learn from the experience. * wanted to learn from the experience.
* 2) Portability. I wanted an implementation that I knew to be portable * 2) Portability. I wanted an implementation that I knew to be portable
* to a reasonable number of platforms. In particular, the algorithm is * to a reasonable number of platforms. In particular, the algorithm is
* designed with little-endian platforms in mind, but I wanted an * designed with little-endian platforms in mind, but I wanted an
* endian-agnostic implementation. * endian-agnostic implementation.
* 3) Compactness. While not an overriding goal, I thought it worth-while * 3) Compactness. While not an overriding goal, I thought it worth-while
* to see if I could reduce the overall size of the result. This is in * to see if I could reduce the overall size of the result. This is in
* keeping with my hopes that this library will be suitable for use in * keeping with my hopes that this library will be suitable for use in
* some embedded environments. * some embedded environments.
* Beyond that, cleanliness and clarity are always worth pursuing. * Beyond that, cleanliness and clarity are always worth pursuing.
* *
* As mentioned above, the code really only makes sense if you are familiar * As mentioned above, the code really only makes sense if you are familiar
* with the MD5 algorithm or are using RFC 1321 as a guide. This code is * with the MD5 algorithm or are using RFC 1321 as a guide. This code is
* quirky, however, so you'll want to be reading carefully. * quirky, however, so you'll want to be reading carefully.
* *
* Yeah...most of the comments are cut-and-paste from my MD4 implementation. * Yeah...most of the comments are cut-and-paste from my MD4 implementation.
* *
* -------------------------------------------------------------------------- ** * -------------------------------------------------------------------------- **
* *
* References: * References:
* IETF RFC 1321: The MD5 Message-Digest Algorithm * IETF RFC 1321: The MD5 Message-Digest Algorithm
* Ron Rivest. IETF, April, 1992 * Ron Rivest. IETF, April, 1992
* *
* ========================================================================== ** * ========================================================================== **
*/ */
/* -------------------------------------------------------------------------- ** /* -------------------------------------------------------------------------- **
* Typedefs: * Typedefs:
*/ */
typedef struct typedef struct
{ {
unsigned int len; unsigned int len;
unsigned int ABCD[4]; unsigned int ABCD[4];
int b_used; int b_used;
unsigned char block[64]; unsigned char block[64];
} auth_md5Ctx; } auth_md5Ctx;
/* -------------------------------------------------------------------------- ** /* -------------------------------------------------------------------------- **
* Functions: * Functions:
*/ */
auth_md5Ctx *auth_md5InitCtx( auth_md5Ctx *ctx ); auth_md5Ctx *auth_md5InitCtx( auth_md5Ctx *ctx );
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Initialize an MD5 context. * Initialize an MD5 context.
* *
* Input: ctx - A pointer to the MD5 context structure to be initialized. * Input: ctx - A pointer to the MD5 context structure to be initialized.
* Contexts are typically created thusly: * Contexts are typically created thusly:
* ctx = (auth_md5Ctx *)malloc( sizeof(auth_md5Ctx) ); * ctx = (auth_md5Ctx *)malloc( sizeof(auth_md5Ctx) );
* *
* Output: A pointer to the initialized context (same as <ctx>). * Output: A pointer to the initialized context (same as <ctx>).
* *
* Notes: The purpose of the context is to make it possible to generate * Notes: The purpose of the context is to make it possible to generate
* an MD5 Message Digest in stages, rather than having to pass a * an MD5 Message Digest in stages, rather than having to pass a
* single large block to a single MD5 function. The context * single large block to a single MD5 function. The context
* structure keeps track of various bits of state information. * structure keeps track of various bits of state information.
* *
* Once the context is initialized, the blocks of message data * Once the context is initialized, the blocks of message data
* are passed to the <auth_md5SumCtx()> function. Once the * are passed to the <auth_md5SumCtx()> function. Once the
* final bit of data has been handed to <auth_md5SumCtx()> the * final bit of data has been handed to <auth_md5SumCtx()> the
* context can be closed out by calling <auth_md5CloseCtx()>, * context can be closed out by calling <auth_md5CloseCtx()>,
* which also calculates the final MD5 result. * which also calculates the final MD5 result.
* *
* Don't forget to free an allocated context structure when * Don't forget to free an allocated context structure when
* you've finished using it. * you've finished using it.
* *
* See Also: <auth_md5SumCtx()>, <auth_md5CloseCtx()> * See Also: <auth_md5SumCtx()>, <auth_md5CloseCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
auth_md5Ctx *auth_md5SumCtx( auth_md5Ctx *ctx, auth_md5Ctx *auth_md5SumCtx( auth_md5Ctx *ctx,
const unsigned char *src, const unsigned char *src,
const int len ); const int len );
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Build an MD5 Message Digest within the given context. * Build an MD5 Message Digest within the given context.
* *
* Input: ctx - Pointer to the context in which the MD5 sum is being * Input: ctx - Pointer to the context in which the MD5 sum is being
* built. * built.
* src - A chunk of source data. This will be used to drive * src - A chunk of source data. This will be used to drive
* the MD5 algorithm. * the MD5 algorithm.
* len - The number of bytes in <src>. * len - The number of bytes in <src>.
* *
* Output: A pointer to the updated context (same as <ctx>). * Output: A pointer to the updated context (same as <ctx>).
* *
* See Also: <auth_md5InitCtx()>, <auth_md5CloseCtx()>, <auth_md5Sum()> * See Also: <auth_md5InitCtx()>, <auth_md5CloseCtx()>, <auth_md5Sum()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
auth_md5Ctx *auth_md5CloseCtx( auth_md5Ctx *ctx, unsigned char *dst ); auth_md5Ctx *auth_md5CloseCtx( auth_md5Ctx *ctx, unsigned char *dst );
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Close an MD5 Message Digest context and generate the final MD5 sum. * Close an MD5 Message Digest context and generate the final MD5 sum.
* *
* Input: ctx - Pointer to the context in which the MD5 sum is being * Input: ctx - Pointer to the context in which the MD5 sum is being
* built. * built.
* dst - A pointer to at least 16 bytes of memory, which will * dst - A pointer to at least 16 bytes of memory, which will
* receive the finished MD5 sum. * receive the finished MD5 sum.
* *
* Output: A pointer to the closed context (same as <ctx>). * Output: A pointer to the closed context (same as <ctx>).
* You might use this to free a malloc'd context structure. :) * You might use this to free a malloc'd context structure. :)
* *
* Notes: The context (<ctx>) is returned in an undefined state. * Notes: The context (<ctx>) is returned in an undefined state.
* It must be re-initialized before re-use. * It must be re-initialized before re-use.
* *
* See Also: <auth_md5InitCtx()>, <auth_md5SumCtx()> * See Also: <auth_md5InitCtx()>, <auth_md5SumCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
unsigned char * MD5(unsigned char * hash, const unsigned char *src, const int len ); unsigned char * MD5( unsigned char * hash, const unsigned char *src, const int len );
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Compute an MD5 message digest. * Compute an MD5 message digest.
* *
* Input: dst - Destination buffer into which the result will be written. * Input: dst - Destination buffer into which the result will be written.
* Must be 16 bytes, minimum. * Must be 16 bytes, minimum.
* src - Source data block to be MD5'd. * src - Source data block to be MD5'd.
* len - The length, in bytes, of the source block. * len - The length, in bytes, of the source block.
* (Note that the length is given in bytes, not bits.) * (Note that the length is given in bytes, not bits.)
* *
* Output: A pointer to <dst>, which will contain the calculated 16-byte * Output: A pointer to <dst>, which will contain the calculated 16-byte
* MD5 message digest. * MD5 message digest.
* *
* Notes: This function is a shortcut. It takes a single input block. * Notes: This function is a shortcut. It takes a single input block.
* For more drawn-out operations, see <auth_md5InitCtx()>. * For more drawn-out operations, see <auth_md5InitCtx()>.
* *
* This function is interface-compatible with the * This function is interface-compatible with the
* <auth_md4Sum()> function in the MD4 module. * <auth_md4Sum()> function in the MD4 module.
* *
* The MD5 algorithm is designed to work on data with an * The MD5 algorithm is designed to work on data with an
* arbitrary *bit* length. Most implementations, this one * arbitrary *bit* length. Most implementations, this one
* included, handle the input data in byte-sized chunks. * included, handle the input data in byte-sized chunks.
* *
* The MD5 algorithm does much of its work using four-byte * The MD5 algorithm does much of its work using four-byte
* words, and so can be tuned for speed based on the endian-ness * words, and so can be tuned for speed based on the endian-ness
* of the host. This implementation is intended to be * of the host. This implementation is intended to be
* endian-neutral, which may make it a teeny bit slower than * endian-neutral, which may make it a teeny bit slower than
* others. ...maybe. * others. ...maybe.
* *
* See Also: <auth_md5InitCtx()> * See Also: <auth_md5InitCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
unsigned char * MD5fromFile(unsigned char *dst, const char *src); unsigned char * MD5fromFile( unsigned char *dst, const char *src );
/* ------------------------------------------------------------------------ ** /* ------------------------------------------------------------------------ **
* Compute an MD5 message digest. * Compute an MD5 message digest.
* *
* Input: dst - Destination buffer into which the result will be written. * Input: dst - Destination buffer into which the result will be written.
* Must be 16 bytes, minimum. * Must be 16 bytes, minimum.
* src - filepath to the file to be MD5'd. * src - filepath to the file to be MD5'd.
* *
* Output: A pointer to <dst>, which will contain the calculated 16-byte * Output: A pointer to <dst>, which will contain the calculated 16-byte
* MD5 message digest. * MD5 message digest.
* *
* Notes: This function is a shortcut. It takes a single input block. * Notes: This function is a shortcut. It takes a single input block.
* For more drawn-out operations, see <auth_md5InitCtx()>. * For more drawn-out operations, see <auth_md5InitCtx()>.
* *
* This function is interface-compatible with the * This function is interface-compatible with the
* <auth_md4Sum()> function in the MD4 module. * <auth_md4Sum()> function in the MD4 module.
* *
* The MD5 algorithm is designed to work on data with an * The MD5 algorithm is designed to work on data with an
* arbitrary *bit* length. Most implementations, this one * arbitrary *bit* length. Most implementations, this one
* included, handle the input data in byte-sized chunks. * included, handle the input data in byte-sized chunks.
* *
* The MD5 algorithm does much of its work using four-byte * The MD5 algorithm does much of its work using four-byte
* words, and so can be tuned for speed based on the endian-ness * words, and so can be tuned for speed based on the endian-ness
* of the host. This implementation is intended to be * of the host. This implementation is intended to be
* endian-neutral, which may make it a teeny bit slower than * endian-neutral, which may make it a teeny bit slower than
* others. ...maybe. * others. ...maybe.
* *
* See Also: <auth_md5InitCtx()> * See Also: <auth_md5InitCtx()>
* *
* ------------------------------------------------------------------------ ** * ------------------------------------------------------------------------ **
*/ */
const char * MD5ToString(const unsigned char *hash, char *dst); const char * MD5ToString( const unsigned char *hash, char *dst );
unsigned char * StringToMD5(const char * hash, unsigned char * dst); unsigned char * StringToMD5( const char * hash, unsigned char * dst );
/* ========================================================================== */ /* ========================================================================== */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* AUTH_MD5_H */ #endif /* AUTH_MD5_H */

View File

@ -22,106 +22,107 @@
#include "patches/fst.h" #include "patches/fst.h"
#include "usbloader/fstfile.h" #include "usbloader/fstfile.h"
s32 dump_banner(const u8* discid,const char * dest) s32 dump_banner( const u8* discid, const char * dest )
{ {
// Mount the disc // Mount the disc
//Disc_SetWBFS(1, (u8*)discid); //Disc_SetWBFS(1, (u8*)discid);
Disc_SetUSB(discid); Disc_SetUSB( discid );
Disc_Open(); Disc_Open();
u64 offset; u64 offset;
s32 ret; s32 ret;
ret = __Disc_FindPartition(&offset); ret = __Disc_FindPartition( &offset );
if (ret < 0) if ( ret < 0 )
return ret; return ret;
ret = WDVD_OpenPartition(offset); ret = WDVD_OpenPartition( offset );
if (ret < 0) { if ( ret < 0 )
//printf("ERROR: OpenPartition(0x%llx) %d\n", offset, ret); {
return ret; //printf("ERROR: OpenPartition(0x%llx) %d\n", offset, ret);
} return ret;
}
// Read where to find the fst.bin // Read where to find the fst.bin
u32 *buffer = memalign(32, 0x20); u32 *buffer = memalign( 32, 0x20 );
if (buffer == NULL) if ( buffer == NULL )
{ {
//Out of memory //Out of memory
return -1; return -1;
} }
ret = WDVD_Read(buffer, 0x20, 0x420); ret = WDVD_Read( buffer, 0x20, 0x420 );
if (ret < 0) if ( ret < 0 )
return ret; return ret;
// Read fst.bin // Read fst.bin
void *fstbuffer = memalign(32, buffer[2]*4); void *fstbuffer = memalign( 32, buffer[2] * 4 );
FST_ENTRY *fst = (FST_ENTRY *)fstbuffer; FST_ENTRY *fst = ( FST_ENTRY * )fstbuffer;
if (fst == NULL) if ( fst == NULL )
{ {
//Out of memory //Out of memory
free(buffer); free( buffer );
return -1; return -1;
} }
ret = WDVD_Read(fstbuffer, buffer[2]*4, buffer[1]*4); ret = WDVD_Read( fstbuffer, buffer[2] * 4, buffer[1] * 4 );
if (ret < 0) if ( ret < 0 )
return ret; return ret;
free(buffer); free( buffer );
// Search the fst.bin // Search the fst.bin
u32 count = fst[0].filelen; u32 count = fst[0].filelen;
int i; int i;
u32 index = 0; u32 index = 0;
for (i=1;i<count;i++) for ( i = 1; i < count; i++ )
{ {
if (strstr(fstfiles(fst, i), "opening.bnr") != NULL) if ( strstr( fstfiles( fst, i ), "opening.bnr" ) != NULL )
{ {
index = i; index = i;
} }
} }
if (index == 0) if ( index == 0 )
{ {
//opening.bnr not found //opening.bnr not found
free(fstbuffer); free( fstbuffer );
return -1; return -1;
} }
// Load the .bnr // Load the .bnr
u8 *banner = memalign(32, fst[index].filelen); u8 *banner = memalign( 32, fst[index].filelen );
if (banner == NULL) if ( banner == NULL )
{ {
//Out of memory //Out of memory
free(fstbuffer); free( fstbuffer );
return -1; return -1;
} }
ret = WDVD_Read((void *)banner, fst[index].filelen, fst[index].fileoffset * 4); ret = WDVD_Read( ( void * )banner, fst[index].filelen, fst[index].fileoffset * 4 );
if (ret < 0) if ( ret < 0 )
return ret; return ret;
WDVD_Reset(); WDVD_Reset();
WDVD_ClosePartition(); WDVD_ClosePartition();
//fatInitDefault(); //fatInitDefault();
//SDCard_Init(); //SDCard_Init();
WDVD_SetUSBMode(NULL, 0); WDVD_SetUSBMode( NULL, 0 );
FILE *fp = fopen(dest, "wb"); FILE *fp = fopen( dest, "wb" );
if(fp) if ( fp )
{ {
fwrite(banner, 1, fst[index].filelen, fp); fwrite( banner, 1, fst[index].filelen, fp );
fclose(fp); fclose( fp );
} }
free(fstbuffer); free( fstbuffer );
free(banner); free( banner );
return 1; return 1;
} }

View File

@ -13,7 +13,7 @@ extern "C"
{ {
#endif #endif
s32 dump_banner(const u8 *discid,const char * dest); s32 dump_banner( const u8 *discid, const char * dest );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -5,66 +5,72 @@
* Shows TPL Banner images * Shows TPL Banner images
***************************************************************************/ ***************************************************************************/
#include "gui_banner.h" #include "gui_banner.h"
GuiBanner::GuiBanner(const char *tplfilepath) GuiBanner::GuiBanner( const char *tplfilepath )
{ {
memory = NULL; memory = NULL;
tplfilesize = 0; tplfilesize = 0;
width = 0; width = 0;
height = 0; height = 0;
FILE *tplfp = fopen(tplfilepath,"rb"); FILE *tplfp = fopen( tplfilepath, "rb" );
if(tplfp !=NULL) { if ( tplfp != NULL )
{
unsigned short heighttemp = 0; unsigned short heighttemp = 0;
unsigned short widthtemp = 0; unsigned short widthtemp = 0;
fseek(tplfp , 0x14, SEEK_SET); fseek( tplfp , 0x14, SEEK_SET );
fread((void*)&heighttemp,1,2,tplfp); fread( ( void* )&heighttemp, 1, 2, tplfp );
fread((void*)&widthtemp,1,2,tplfp); fread( ( void* )&widthtemp, 1, 2, tplfp );
fseek (tplfp , 0 , SEEK_END); fseek ( tplfp , 0 , SEEK_END );
tplfilesize = ftell (tplfp); tplfilesize = ftell ( tplfp );
rewind (tplfp); rewind ( tplfp );
memory = memalign(32, tplfilesize); memory = memalign( 32, tplfilesize );
if(!memory) { if ( !memory )
fclose(tplfp); {
fclose( tplfp );
return; return;
} }
fread(memory, 1, tplfilesize, tplfp); fread( memory, 1, tplfilesize, tplfp );
fclose(tplfp); fclose( tplfp );
TPLFile tplfile; TPLFile tplfile;
int ret; int ret;
ret = TPL_OpenTPLFromMemory(&tplfile, memory, tplfilesize); ret = TPL_OpenTPLFromMemory( &tplfile, memory, tplfilesize );
if(ret < 0) { if ( ret < 0 )
free(memory); {
free( memory );
memory = NULL; memory = NULL;
return; return;
} }
ret = TPL_GetTexture(&tplfile,0,&texObj); ret = TPL_GetTexture( &tplfile, 0, &texObj );
if(ret < 0) { if ( ret < 0 )
free(memory); {
free( memory );
memory = NULL; memory = NULL;
return; return;
} }
TPL_CloseTPLFile(&tplfile); TPL_CloseTPLFile( &tplfile );
width = widthtemp; width = widthtemp;
height = heighttemp; height = heighttemp;
widescreen = 0; widescreen = 0;
filecheck = true; filecheck = true;
} else { }
filecheck = false; else
fclose(tplfp); {
filecheck = false;
fclose( tplfp );
} }
} }
GuiBanner::GuiBanner(void *mem, u32 len, int w, int h) GuiBanner::GuiBanner( void *mem, u32 len, int w, int h )
{ {
if(!mem || !len) if ( !mem || !len )
return; return;
memory = mem; memory = mem;
tplfilesize = len; tplfilesize = len;
@ -75,40 +81,43 @@ GuiBanner::GuiBanner(void *mem, u32 len, int w, int h)
int ret; int ret;
ret = TPL_OpenTPLFromMemory(&tplfile, memory, tplfilesize); ret = TPL_OpenTPLFromMemory( &tplfile, memory, tplfilesize );
if(ret < 0) { if ( ret < 0 )
free(memory); {
free( memory );
memory = NULL; memory = NULL;
return; return;
} }
ret = TPL_GetTexture(&tplfile,0,&texObj); ret = TPL_GetTexture( &tplfile, 0, &texObj );
if(ret < 0) { if ( ret < 0 )
free(memory); {
free( memory );
memory = NULL; memory = NULL;
return; return;
} }
TPL_CloseTPLFile(&tplfile); TPL_CloseTPLFile( &tplfile );
filecheck = true; filecheck = true;
} }
GuiBanner::~GuiBanner()
{
if(memory != NULL) {
free(memory);
memory = NULL;
}
}
void GuiBanner::Draw()
{
LOCK(this);
if(!filecheck ||!this->IsVisible())
return;
float currScale = this->GetScale();
Menu_DrawTPLImg(this->GetLeft(), this->GetTop(), 0, width, height, &texObj, imageangle, widescreen ? currScale*0.80 : currScale, currScale, this->GetAlpha(), xx1,yy1,xx2,yy2,xx3,yy3,xx4,yy4); GuiBanner::~GuiBanner()
{
this->UpdateEffects(); if ( memory != NULL )
} {
free( memory );
memory = NULL;
}
}
void GuiBanner::Draw()
{
LOCK( this );
if ( !filecheck || !this->IsVisible() )
return;
float currScale = this->GetScale();
Menu_DrawTPLImg( this->GetLeft(), this->GetTop(), 0, width, height, &texObj, imageangle, widescreen ? currScale*0.80 : currScale, currScale, this->GetAlpha(), xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4 );
this->UpdateEffects();
}

View File

@ -12,24 +12,24 @@
class GuiBanner : public GuiImage class GuiBanner : public GuiImage
{ {
public: public:
//!Constructor //!Constructor
//!\param tplfilepath Path of the tpl file //!\param tplfilepath Path of the tpl file
GuiBanner(const char *tplfilepath); GuiBanner( const char *tplfilepath );
//!Constructor //!Constructor
//!\param mem Memory of the loaded tpl //!\param mem Memory of the loaded tpl
//!\param len Filesize of the tpl //!\param len Filesize of the tpl
//!\param w Width of the tpl //!\param w Width of the tpl
//!\param h Height of the tpl //!\param h Height of the tpl
GuiBanner(void *mem, u32 len, int w, int h); GuiBanner( void *mem, u32 len, int w, int h );
//!Destructor //!Destructor
~GuiBanner(); ~GuiBanner();
void Draw(); void Draw();
protected: protected:
void * memory; void * memory;
bool filecheck; bool filecheck;
u32 tplfilesize; u32 tplfilesize;
GXTexObj texObj; GXTexObj texObj;
}; };
#endif /* _GUIBANNER_H_ */ #endif /* _GUIBANNER_H_ */

View File

@ -28,51 +28,52 @@
#include "../ramdisk/ramdisk.h" #include "../ramdisk/ramdisk.h"
#include "../listfiles.h" #include "../listfiles.h"
u16 be16(const u8 *p) u16 be16( const u8 *p )
{ {
return (p[0] << 8) | p[1]; return ( p[0] << 8 ) | p[1];
} }
u32 be32(const u8 *p) u32 be32( const u8 *p )
{ {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; return ( p[0] << 24 ) | ( p[1] << 16 ) | ( p[2] << 8 ) | p[3];
} }
u64 be64(const u8 *p) u64 be64( const u8 *p )
{ {
return ((u64)be32(p) << 32) | be32(p + 4); return ( ( u64 )be32( p ) << 32 ) | be32( p + 4 );
} }
u64 be34(const u8 *p) u64 be34( const u8 *p )
{ {
return 4 * (u64)be32(p); return 4 * ( u64 )be32( p );
} }
void wbe16(u8 *p, u16 x) void wbe16( u8 *p, u16 x )
{ {
p[0] = x >> 8; p[0] = x >> 8;
p[1] = x; p[1] = x;
} }
void wbe32(u8 *p, u32 x) void wbe32( u8 *p, u32 x )
{ {
wbe16(p, x >> 16); wbe16( p, x >> 16 );
wbe16(p + 2, x); wbe16( p + 2, x );
} }
void wbe64(u8 *p, u64 x) void wbe64( u8 *p, u64 x )
{ {
wbe32(p, x >> 32); wbe32( p, x >> 32 );
wbe32(p + 4, x); wbe32( p + 4, x );
} }
void md5(u8 *data, u32 len, u8 *hash) void md5( u8 *data, u32 len, u8 *hash )
{ {
MD5(hash, data, len); MD5( hash, data, len );
} }
typedef struct { typedef struct
{
u8 zeroes[0x40]; u8 zeroes[0x40];
u32 imet; // "IMET" u32 imet; // "IMET"
u8 zero_six_zero_three[8]; // fixed, unknown purpose u8 zero_six_zero_three[8]; // fixed, unknown purpose
@ -89,441 +90,474 @@ typedef struct {
u8 crypto[0x10]; u8 crypto[0x10];
} imet_data_t; } imet_data_t;
typedef struct { typedef struct
u32 imd5_tag; // 0x494D4435 "IMD5"; {
u32 size; // size of the rest of part B, starting from next field. u32 imd5_tag; // 0x494D4435 "IMD5";
u8 zeroes[8]; u32 size; // size of the rest of part B, starting from next field.
u8 md5[16]; u8 zeroes[8];
u32 payload_tag; // 0x4C5A3737 "LZ77" if this is lz77 u8 md5[16];
u32 payload_data; u32 payload_tag; // 0x4C5A3737 "LZ77" if this is lz77
u32 payload_data;
} imd5_header_t; } imd5_header_t;
typedef struct typedef struct
{ {
u16 type; u16 type;
u16 name_offset; u16 name_offset;
u32 data_offset; // == absolut offset från U.8- headerns början u32 data_offset; // == absolut offset från U.8- headerns början
u32 size; // last included file num for directories u32 size; // last included file num for directories
} U8_node; } U8_node;
typedef struct typedef struct
{ {
u32 tag; // 0x55AA382D "U.8-" u32 tag; // 0x55AA382D "U.8-"
u32 rootnode_offset; // offset to root_node, always 0x20. u32 rootnode_offset; // offset to root_node, always 0x20.
u32 header_size; // size of header from root_node to end of string table. u32 header_size; // size of header from root_node to end of string table.
u32 data_offset; // offset to data -- this is rootnode_offset + header_size, aligned to 0x40. u32 data_offset; // offset to data -- this is rootnode_offset + header_size, aligned to 0x40.
u8 zeroes[16]; u8 zeroes[16];
} U8_archive_header; } U8_archive_header;
static int write_file(void* data, size_t size, char* name) static int write_file( void* data, size_t size, char* name )
{ {
size_t written=0; size_t written = 0;
FILE *out; FILE *out;
out = fopen(name, "wb"); out = fopen( name, "wb" );
if(out) if ( out )
{ {
written = fwrite(data, 1, size, out); written = fwrite( data, 1, size, out );
fclose(out); fclose( out );
} }
return (written == size) ? 1 : -1; return ( written == size ) ? 1 : -1;
} }
u8* decompress_lz77(u8 *data, size_t data_size, size_t* decompressed_size) u8* decompress_lz77( u8 *data, size_t data_size, size_t* decompressed_size )
{ {
u8 *data_end; u8 *data_end;
u8 *decompressed_data; u8 *decompressed_data;
size_t unpacked_size; size_t unpacked_size;
u8 *in_ptr; u8 *in_ptr;
u8 *out_ptr; u8 *out_ptr;
u8 *out_end; u8 *out_end;
in_ptr = data; in_ptr = data;
data_end = data + data_size; data_end = data + data_size;
// Assume this for now and grow when needed // Assume this for now and grow when needed
unpacked_size = data_size; unpacked_size = data_size;
decompressed_data = malloc(unpacked_size); decompressed_data = malloc( unpacked_size );
out_end = decompressed_data + unpacked_size; out_end = decompressed_data + unpacked_size;
out_ptr = decompressed_data; out_ptr = decompressed_data;
while (in_ptr < data_end) { while ( in_ptr < data_end )
int bit; {
u8 bitmask = *in_ptr; int bit;
u8 bitmask = *in_ptr;
in_ptr++; in_ptr++;
for (bit = 0x80; bit != 0; bit >>= 1) { for ( bit = 0x80; bit != 0; bit >>= 1 )
if (bitmask & bit) { {
// Next section is compressed if ( bitmask & bit )
u8 rep_length; {
u16 rep_offset; // Next section is compressed
u8 rep_length;
u16 rep_offset;
rep_length = (*in_ptr >> 4) + 3; rep_length = ( *in_ptr >> 4 ) + 3;
rep_offset = *in_ptr & 0x0f; rep_offset = *in_ptr & 0x0f;
in_ptr++; in_ptr++;
rep_offset = *in_ptr | (rep_offset << 8); rep_offset = *in_ptr | ( rep_offset << 8 );
in_ptr++; in_ptr++;
if (out_ptr-decompressed_data < rep_offset) { if ( out_ptr - decompressed_data < rep_offset )
return NULL; {
} return NULL;
}
for ( ; rep_length > 0; rep_length--) { for ( ; rep_length > 0; rep_length-- )
*out_ptr = out_ptr[-rep_offset-1]; {
out_ptr++; *out_ptr = out_ptr[-rep_offset-1];
if (out_ptr >= out_end) { out_ptr++;
// Need to grow buffer if ( out_ptr >= out_end )
decompressed_data = realloc(decompressed_data, unpacked_size*2); {
out_ptr = decompressed_data + unpacked_size; // Need to grow buffer
unpacked_size *= 2; decompressed_data = realloc( decompressed_data, unpacked_size * 2 );
out_end = decompressed_data + unpacked_size; out_ptr = decompressed_data + unpacked_size;
} unpacked_size *= 2;
out_end = decompressed_data + unpacked_size;
}
}
}
else
{
// Just copy byte
*out_ptr = *in_ptr;
out_ptr++;
if ( out_ptr >= out_end )
{
// Need to grow buffer
decompressed_data = realloc( decompressed_data, unpacked_size * 2 );
out_ptr = decompressed_data + unpacked_size;
unpacked_size *= 2;
out_end = decompressed_data + unpacked_size;
}
in_ptr++;
}
} }
} else { }
// Just copy byte
*out_ptr = *in_ptr;
out_ptr++;
if (out_ptr >= out_end) {
// Need to grow buffer
decompressed_data = realloc(decompressed_data, unpacked_size*2);
out_ptr = decompressed_data + unpacked_size;
unpacked_size *= 2;
out_end = decompressed_data + unpacked_size;
}
in_ptr++;
}
}
}
*decompressed_size = (out_ptr - decompressed_data); *decompressed_size = ( out_ptr - decompressed_data );
return decompressed_data; return decompressed_data;
} }
static int write_imd5_lz77(u8* data, size_t size, char* outname) static int write_imd5_lz77( u8* data, size_t size, char* outname )
{ {
imd5_header_t* header = (imd5_header_t*) data; imd5_header_t* header = ( imd5_header_t* ) data;
u32 tag; u32 tag;
u32 size_in_imd5; u32 size_in_imd5;
u8 md5_calc[16]; u8 md5_calc[16];
u8 *decompressed_data; u8 *decompressed_data;
size_t decompressed_size; size_t decompressed_size;
tag = be32((u8*) &header->imd5_tag); tag = be32( ( u8* ) & header->imd5_tag );
if (tag != 0x494D4435) { if ( tag != 0x494D4435 )
return -4; {
} return -4;
}
md5(data+32, size-32, md5_calc); md5( data + 32, size - 32, md5_calc );
if (memcmp(&header->md5, md5_calc, 0x10)) { if ( memcmp( &header->md5, md5_calc, 0x10 ) )
return -5; {
} return -5;
}
size_in_imd5 = be32((u8*) &header->size); size_in_imd5 = be32( ( u8* ) & header->size );
if (size_in_imd5 != size - 32) { if ( size_in_imd5 != size - 32 )
return -6; {
} return -6;
}
tag = be32((u8*) &header->payload_tag); tag = be32( ( u8* ) & header->payload_tag );
if (tag == 0x4C5A3737) { if ( tag == 0x4C5A3737 )
// "LZ77" - uncompress {
decompressed_data = decompress_lz77(data + sizeof(imd5_header_t), size - sizeof(imd5_header_t), &decompressed_size); // "LZ77" - uncompress
if(decompressed_data == NULL) decompressed_data = decompress_lz77( data + sizeof( imd5_header_t ), size - sizeof( imd5_header_t ), &decompressed_size );
return -7; if ( decompressed_data == NULL )
write_file(decompressed_data, decompressed_size, outname); return -7;
//printf(", uncompressed %d bytes, md5 ok", decompressed_size); write_file( decompressed_data, decompressed_size, outname );
//printf(", uncompressed %d bytes, md5 ok", decompressed_size);
free(decompressed_data); free( decompressed_data );
} else { }
write_file(&header->payload_tag, size-32, outname); else
//printf(", md5 ok"); {
} write_file( &header->payload_tag, size - 32, outname );
return 0; //printf(", md5 ok");
}
return 0;
} }
static int do_U8_archive(FILE *fp) static int do_U8_archive( FILE *fp )
{ {
U8_archive_header header; U8_archive_header header;
U8_node root_node; U8_node root_node;
u32 tag; u32 tag;
u32 num_nodes; u32 num_nodes;
U8_node* nodes; U8_node* nodes;
u8* string_table; u8* string_table;
size_t rest_size; size_t rest_size;
unsigned int i; unsigned int i;
u32 data_offset; u32 data_offset;
u32 current_offset; u32 current_offset;
u16 dir_stack[16]; u16 dir_stack[16];
int dir_index = 0; int dir_index = 0;
fread(&header, 1, sizeof header, fp); fread( &header, 1, sizeof header, fp );
tag = be32((u8*) &header.tag); tag = be32( ( u8* ) & header.tag );
if (tag != 0x55AA382D) { if ( tag != 0x55AA382D )
return -1; {
} return -1;
}
fread(&root_node, 1, sizeof(root_node), fp); fread( &root_node, 1, sizeof( root_node ), fp );
num_nodes = be32((u8*) &root_node.size) - 1; num_nodes = be32( ( u8* ) & root_node.size ) - 1;
//printf("Number of files: %d\n", num_nodes); //printf("Number of files: %d\n", num_nodes);
nodes = malloc(sizeof(U8_node) * (num_nodes)); nodes = malloc( sizeof( U8_node ) * ( num_nodes ) );
fread(nodes, 1, num_nodes * sizeof(U8_node), fp); fread( nodes, 1, num_nodes * sizeof( U8_node ), fp );
data_offset = be32((u8*) &header.data_offset); data_offset = be32( ( u8* ) & header.data_offset );
rest_size = data_offset - sizeof(header) - (num_nodes+1)*sizeof(U8_node); rest_size = data_offset - sizeof( header ) - ( num_nodes + 1 ) * sizeof( U8_node );
string_table = malloc(rest_size); string_table = malloc( rest_size );
fread(string_table, 1, rest_size, fp); fread( string_table, 1, rest_size, fp );
current_offset = data_offset; current_offset = data_offset;
for (i = 0; i < num_nodes; i++) { for ( i = 0; i < num_nodes; i++ )
U8_node* node = &nodes[i]; {
u16 type = be16((u8*)&node->type); U8_node* node = &nodes[i];
u16 name_offset = be16((u8*)&node->name_offset); u16 type = be16( ( u8* ) & node->type );
u32 my_data_offset = be32((u8*)&node->data_offset); u16 name_offset = be16( ( u8* ) & node->name_offset );
u32 size = be32((u8*)&node->size); u32 my_data_offset = be32( ( u8* ) & node->data_offset );
char* name = (char*) &string_table[name_offset]; u32 size = be32( ( u8* ) & node->size );
u8* file_data; char* name = ( char* ) & string_table[name_offset];
u8* file_data;
if (type == 0x0100) { if ( type == 0x0100 )
// Directory {
mkdir(name, 0777); // Directory
chdir(name); mkdir( name, 0777 );
dir_stack[++dir_index] = size; chdir( name );
//printf("%*s%s/\n", dir_index, "", name); dir_stack[++dir_index] = size;
} else { //printf("%*s%s/\n", dir_index, "", name);
// Normal file
u8 padding[32];
if (type != 0x0000) {
free(string_table);
return -2;
}
if (current_offset < my_data_offset) {
int diff = my_data_offset - current_offset;
if (diff > 32) {
free(string_table);
return -3;
} }
fread(padding, 1, diff, fp); else
current_offset += diff; {
} // Normal file
u8 padding[32];
file_data = malloc(size); if ( type != 0x0000 )
fread(file_data, 1, size, fp); {
//printf("%*s %s (%d bytes", dir_index, "", name, size); free( string_table );
int result; return -2;
result = write_imd5_lz77(file_data, size, name); }
if(result < 0)
{free(string_table); if ( current_offset < my_data_offset )
return result; {
} int diff = my_data_offset - current_offset;
//printf(")\n");
current_offset += size; if ( diff > 32 )
{
free( string_table );
return -3;
}
fread( padding, 1, diff, fp );
current_offset += diff;
}
file_data = malloc( size );
fread( file_data, 1, size, fp );
//printf("%*s %s (%d bytes", dir_index, "", name, size);
int result;
result = write_imd5_lz77( file_data, size, name );
if ( result < 0 )
{
free( string_table );
return result;
}
//printf(")\n");
current_offset += size;
}
while ( dir_stack[dir_index] == i + 2 && dir_index > 0 )
{
chdir( ".." );
dir_index--;
}
}
free( string_table );
return 0;
}
static void do_imet_header( FILE *fp )
{
imet_data_t header;
fread( &header, 1, sizeof header, fp );
write_file( &header, sizeof( header ), "header.imet" );
}
void do_U8_archivebanner( FILE *fp )
{
U8_archive_header header;
U8_node root_node;
u32 tag;
u32 num_nodes;
U8_node* nodes;
u8* string_table;
size_t rest_size;
unsigned int i;
u32 data_offset;
u16 dir_stack[16];
int dir_index = 0;
fread( &header, 1, sizeof header, fp );
tag = be32( ( u8* ) & header.tag );
if ( tag != 0x55AA382D )
{
//printf("No U8 tag");
exit( 0 );
} }
while (dir_stack[dir_index] == i+2 && dir_index > 0) { fread( &root_node, 1, sizeof( root_node ), fp );
chdir(".."); num_nodes = be32( ( u8* ) & root_node.size ) - 1;
dir_index--; printf( "Number of files: %d\n", num_nodes );
nodes = malloc( sizeof( U8_node ) * ( num_nodes ) );
fread( nodes, 1, num_nodes * sizeof( U8_node ), fp );
data_offset = be32( ( u8* ) & header.data_offset );
rest_size = data_offset - sizeof( header ) - ( num_nodes + 1 ) * sizeof( U8_node );
string_table = malloc( rest_size );
fread( string_table, 1, rest_size, fp );
for ( i = 0; i < num_nodes; i++ )
{
U8_node* node = &nodes[i];
u16 type = be16( ( u8* ) & node->type );
u16 name_offset = be16( ( u8* ) & node->name_offset );
u32 my_data_offset = be32( ( u8* ) & node->data_offset );
u32 size = be32( ( u8* ) & node->size );
char* name = ( char* ) & string_table[name_offset];
u8* file_data;
if ( type == 0x0100 )
{
// Directory
mkdir( name, 0777 );
chdir( name );
dir_stack[++dir_index] = size;
//printf("%*s%s/\n", dir_index, "", name);
}
else
{
// Normal file
if ( type != 0x0000 )
{
printf( "Unknown type" );
exit( 0 );
}
fseek( fp, my_data_offset, SEEK_SET );
file_data = malloc( size );
fread( file_data, 1, size, fp );
write_file( file_data, size, name );
free( file_data );
//printf("%*s %s (%d bytes)\n", dir_index, "", name, size);
}
while ( dir_stack[dir_index] == i + 2 && dir_index > 0 )
{
chdir( ".." );
dir_index--;
}
} }
} free( string_table );
free(string_table);
return 0;
} }
static void do_imet_header(FILE *fp) int extractbnrfile( const char * filepath, const char * destpath )
{
imet_data_t header;
fread(&header, 1, sizeof header, fp);
write_file(&header, sizeof(header), "header.imet");
}
void do_U8_archivebanner(FILE *fp)
{
U8_archive_header header;
U8_node root_node;
u32 tag;
u32 num_nodes;
U8_node* nodes;
u8* string_table;
size_t rest_size;
unsigned int i;
u32 data_offset;
u16 dir_stack[16];
int dir_index = 0;
fread(&header, 1, sizeof header, fp);
tag = be32((u8*) &header.tag);
if (tag != 0x55AA382D) {
//printf("No U8 tag");
exit(0);
}
fread(&root_node, 1, sizeof(root_node), fp);
num_nodes = be32((u8*) &root_node.size) - 1;
printf("Number of files: %d\n", num_nodes);
nodes = malloc(sizeof(U8_node) * (num_nodes));
fread(nodes, 1, num_nodes * sizeof(U8_node), fp);
data_offset = be32((u8*) &header.data_offset);
rest_size = data_offset - sizeof(header) - (num_nodes+1)*sizeof(U8_node);
string_table = malloc(rest_size);
fread(string_table, 1, rest_size, fp);
for (i = 0; i < num_nodes; i++) {
U8_node* node = &nodes[i];
u16 type = be16((u8*)&node->type);
u16 name_offset = be16((u8*)&node->name_offset);
u32 my_data_offset = be32((u8*)&node->data_offset);
u32 size = be32((u8*)&node->size);
char* name = (char*) &string_table[name_offset];
u8* file_data;
if (type == 0x0100) {
// Directory
mkdir(name, 0777);
chdir(name);
dir_stack[++dir_index] = size;
//printf("%*s%s/\n", dir_index, "", name);
} else {
// Normal file
if (type != 0x0000) {
printf("Unknown type");
exit(0);
}
fseek(fp, my_data_offset, SEEK_SET);
file_data = malloc(size);
fread(file_data, 1, size, fp);
write_file(file_data, size, name);
free(file_data);
//printf("%*s %s (%d bytes)\n", dir_index, "", name, size);
}
while (dir_stack[dir_index] == i+2 && dir_index > 0) {
chdir("..");
dir_index--;
}
}
free(string_table);
}
int extractbnrfile(const char * filepath, const char * destpath)
{ {
int ret = -1; int ret = -1;
FILE *fp = fopen(filepath, "rb"); FILE *fp = fopen( filepath, "rb" );
if(fp) if ( fp )
{ {
subfoldercreate(destpath); subfoldercreate( destpath );
chdir(destpath); chdir( destpath );
do_imet_header(fp); do_imet_header( fp );
ret = do_U8_archive(fp); ret = do_U8_archive( fp );
fclose(fp); fclose( fp );
} }
return ret; return ret;
} }
int unpackBin(const char * filename,const char * outdir) int unpackBin( const char * filename, const char * outdir )
{ {
FILE *fp = fopen(filename,"rb");; FILE *fp = fopen( filename, "rb" );;
if(fp) if ( fp )
{ {
subfoldercreate(outdir); subfoldercreate( outdir );
chdir(outdir); chdir( outdir );
do_U8_archivebanner(fp); do_U8_archivebanner( fp );
fclose(fp); fclose( fp );
return 1; return 1;
} }
return 0; return 0;
} }
#define TMP_PATH(s) "BANNER:/dump"s #define TMP_PATH(s) "BANNER:/dump"s
//#define TMP_PATH(s) "SD:/dump"s //#define TMP_PATH(s) "SD:/dump"s
int unpackBanner(const u8 *gameid, int what, const char *outdir) int unpackBanner( const u8 *gameid, int what, const char *outdir )
{ {
char path[256]; char path[256];
if(!ramdiskMount("BANNER", NULL)) return -1; if ( !ramdiskMount( "BANNER", NULL ) ) return -1;
subfoldercreate(TMP_PATH("/")); subfoldercreate( TMP_PATH( "/" ) );
s32 ret = dump_banner(gameid, TMP_PATH("/opening.bnr")); s32 ret = dump_banner( gameid, TMP_PATH( "/opening.bnr" ) );
if (ret != 1) if ( ret != 1 )
{ {
ret = -1; ret = -1;
goto error2; goto error2;
} }
ret = extractbnrfile(TMP_PATH("/opening.bnr"), TMP_PATH("/")); ret = extractbnrfile( TMP_PATH( "/opening.bnr" ), TMP_PATH( "/" ) );
if (ret != 0) if ( ret != 0 )
{ {
ret = -1; ret = -1;
goto error2; goto error2;
} }
if(what & UNPACK_BANNER_BIN) if ( what & UNPACK_BANNER_BIN )
{ {
snprintf(path, sizeof(path),"%sbanner/", outdir); snprintf( path, sizeof( path ), "%sbanner/", outdir );
ret = unpackBin(TMP_PATH("/meta/banner.bin"), path); ret = unpackBin( TMP_PATH( "/meta/banner.bin" ), path );
if (ret != 1) if ( ret != 1 )
{ {
ret = -1; ret = -1;
goto error2; goto error2;
} }
} }
if(what & UNPACK_ICON_BIN) if ( what & UNPACK_ICON_BIN )
{ {
snprintf(path, sizeof(path),"%sicon/", outdir); snprintf( path, sizeof( path ), "%sicon/", outdir );
ret = unpackBin(TMP_PATH("/meta/icon.bin"), path); ret = unpackBin( TMP_PATH( "/meta/icon.bin" ), path );
if (ret != 1) if ( ret != 1 )
{ {
ret = -1; ret = -1;
goto error2; goto error2;
} }
} }
if(what & UNPACK_SOUND_BIN) if ( what & UNPACK_SOUND_BIN )
{ {
snprintf(path, sizeof(path),"%ssound.bin", outdir); snprintf( path, sizeof( path ), "%ssound.bin", outdir );
FILE *fp = fopen(TMP_PATH("/meta/sound.bin"), "rb"); FILE *fp = fopen( TMP_PATH( "/meta/sound.bin" ), "rb" );
if(fp) if ( fp )
{ {
size_t size; size_t size;
u8 *data; u8 *data;
fseek(fp, 0, SEEK_END); fseek( fp, 0, SEEK_END );
size = ftell(fp); size = ftell( fp );
if(!size) if ( !size )
{ {
ret = -1; ret = -1;
goto error; goto error;
} }
fseek(fp, 0, SEEK_SET); fseek( fp, 0, SEEK_SET );
data = (u8 *)malloc(size); data = ( u8 * )malloc( size );
if(!data) if ( !data )
{ {
ret = -1; ret = -1;
goto error; goto error;
} }
if(fread(data, 1, size, fp) != size) if ( fread( data, 1, size, fp ) != size )
{ {
ret = -1; ret = -1;
goto error; goto error;
} }
ret = write_file(data, size, path); ret = write_file( data, size, path );
} }
error: fclose(fp); error: fclose( fp );
} }
ramdiskUnmount("BANNER"); ramdiskUnmount( "BANNER" );
error2: error2:
if(ret < 0) if ( ret < 0 )
return ret; return ret;
return 1; return 1;
} }

View File

@ -13,32 +13,32 @@ extern "C"
{ {
#endif #endif
/*********************************************************** /***********************************************************
* Error description: * Error description:
* 0 Successfully extracted * 0 Successfully extracted
* -1 No U8 tag * -1 No U8 tag
* -2 Unknown type * -2 Unknown type
* -3 Archive inconsistency, too much padding * -3 Archive inconsistency, too much padding
* -4 No IMD5 tag * -4 No IMD5 tag
* -5 MD5 mismatch * -5 MD5 mismatch
* -6 Size mismatch * -6 Size mismatch
* -7 Inconsistency in LZ77 encoding * -7 Inconsistency in LZ77 encoding
************************************************************/ ************************************************************/
//! Extract opening.bnr from filepath to destpath //! Extract opening.bnr from filepath to destpath
//! Files extracted: banner.bin icon.bin and sound.bin //! Files extracted: banner.bin icon.bin and sound.bin
int extractbnrfile(const char * filepath, const char * destpath); int extractbnrfile( const char * filepath, const char * destpath );
int unpackBin(const char * filename,const char * outdir); int unpackBin( const char * filename, const char * outdir );
#define UNPACK_BANNER_BIN 1 /* extract banner.bin to outdir/banner/ */ #define UNPACK_BANNER_BIN 1 /* extract banner.bin to outdir/banner/ */
#define UNPACK_ICON_BIN 2 /* extract icon.bin to outdir/icon/ */ #define UNPACK_ICON_BIN 2 /* extract icon.bin to outdir/icon/ */
#define UNPACK_SOUND_BIN 4 /* copies sound.bin to outdir/sound.bin */ #define UNPACK_SOUND_BIN 4 /* copies sound.bin to outdir/sound.bin */
#define UNPACK_ALL (UNPACK_SOUND_BIN | UNPACK_ICON_BIN | UNPACK_BANNER_BIN) #define UNPACK_ALL (UNPACK_SOUND_BIN | UNPACK_ICON_BIN | UNPACK_BANNER_BIN)
int unpackBanner(const u8 * gameid, int what, const char *outdir); int unpackBanner( const u8 * gameid, int what, const char *outdir );
//! Extract the lz77 compressed banner, icon and sound .bin //! Extract the lz77 compressed banner, icon and sound .bin
u8* decompress_lz77(u8 *data, size_t data_size, size_t* decompressed_size); u8* decompress_lz77( u8 *data, size_t data_size, size_t* decompressed_size );
u16 be16(const u8 *p); u16 be16( const u8 *p );
u32 be32(const u8 *p); u32 be32( const u8 *p );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -13,197 +13,197 @@
struct IMD5Header struct IMD5Header
{ {
u32 fcc; u32 fcc;
u32 filesize; u32 filesize;
u8 zeroes[8]; u8 zeroes[8];
u8 crypto[16]; u8 crypto[16];
} __attribute__((packed)); } __attribute__( ( packed ) );
struct IMETHeader struct IMETHeader
{ {
u8 zeroes[64]; u8 zeroes[64];
u32 fcc; u32 fcc;
u8 unk[8]; u8 unk[8];
u32 iconSize; u32 iconSize;
u32 bannerSize; u32 bannerSize;
u32 soundSize; u32 soundSize;
u32 flag1; u32 flag1;
u8 names[7][84]; u8 names[7][84];
u8 zeroes_2[0x348]; u8 zeroes_2[0x348];
u8 crypto[16]; u8 crypto[16];
} __attribute__((packed)); } __attribute__( ( packed ) );
struct U8Header struct U8Header
{ {
u32 fcc; u32 fcc;
u32 rootNodeOffset; u32 rootNodeOffset;
u32 headerSize; u32 headerSize;
u32 dataOffset; u32 dataOffset;
u8 zeroes[16]; u8 zeroes[16];
} __attribute__((packed)); } __attribute__( ( packed ) );
struct U8Entry struct U8Entry
{ {
struct struct
{ {
u32 fileType : 8; u32 fileType : 8;
u32 nameOffset : 24; u32 nameOffset : 24;
}; };
u32 fileOffset; u32 fileOffset;
union union
{ {
u32 fileLength; u32 fileLength;
u32 numEntries; u32 numEntries;
}; };
} __attribute__((packed)); } __attribute__( ( packed ) );
struct LZ77Info struct LZ77Info
{ {
u16 length : 4; u16 length : 4;
u16 offset : 12; u16 offset : 12;
} __attribute__((packed)); } __attribute__( ( packed ) );
static char *u8Filename(const U8Entry *fst, int i) static char *u8Filename( const U8Entry *fst, int i )
{ {
return (char *)(fst + fst[0].numEntries) + fst[i].nameOffset; return ( char * )( fst + fst[0].numEntries ) + fst[i].nameOffset;
} }
inline u32 le32(u32 i) inline u32 le32( u32 i )
{ {
return ((i & 0xFF) << 24) | ((i & 0xFF00) << 8) | ((i & 0xFF0000) >> 8) | ((i & 0xFF000000) >> 24); return ( ( i & 0xFF ) << 24 ) | ( ( i & 0xFF00 ) << 8 ) | ( ( i & 0xFF0000 ) >> 8 ) | ( ( i & 0xFF000000 ) >> 24 );
} }
inline u16 le16(u16 i) inline u16 le16( u16 i )
{ {
return ((i & 0xFF) << 8) | ((i & 0xFF00) >> 8); return ( ( i & 0xFF ) << 8 ) | ( ( i & 0xFF00 ) >> 8 );
} }
static u8 *uncompressLZ77(const u8 *inBuf, u32 inLength, u32 &size) static u8 *uncompressLZ77( const u8 *inBuf, u32 inLength, u32 &size )
{ {
u8 *buffer = NULL; u8 *buffer = NULL;
if (inLength <= 0x8 || *((const u32 *)inBuf) != 0x4C5A3737 /*"LZ77"*/ || inBuf[4] != 0x10) if ( inLength <= 0x8 || *( ( const u32 * )inBuf ) != 0x4C5A3737 /*"LZ77"*/ || inBuf[4] != 0x10 )
return NULL; return NULL;
u32 uncSize = le32(((const u32 *)inBuf)[1] << 8); u32 uncSize = le32( ( ( const u32 * )inBuf )[1] << 8 );
const u8 *inBufEnd = inBuf + inLength; const u8 *inBufEnd = inBuf + inLength;
inBuf += 8; inBuf += 8;
buffer = new(std::nothrow) u8[uncSize]; buffer = new( std::nothrow ) u8[uncSize];
if (!buffer) if ( !buffer )
return buffer; return buffer;
u8 *bufCur = buffer; u8 *bufCur = buffer;
u8 *bufEnd = buffer + uncSize; u8 *bufEnd = buffer + uncSize;
while (bufCur < bufEnd && inBuf < inBufEnd) while ( bufCur < bufEnd && inBuf < inBufEnd )
{ {
u8 flags = *inBuf; u8 flags = *inBuf;
++inBuf; ++inBuf;
for (int i = 0; i < 8 && bufCur < bufEnd && inBuf < inBufEnd; ++i) for ( int i = 0; i < 8 && bufCur < bufEnd && inBuf < inBufEnd; ++i )
{ {
if ((flags & 0x80) != 0) if ( ( flags & 0x80 ) != 0 )
{ {
const LZ77Info &info = *(const LZ77Info *)inBuf; const LZ77Info &info = *( const LZ77Info * )inBuf;
inBuf += sizeof (LZ77Info); inBuf += sizeof ( LZ77Info );
int length = info.length + 3; int length = info.length + 3;
if (bufCur - info.offset - 1 < buffer || bufCur + length > bufEnd) if ( bufCur - info.offset - 1 < buffer || bufCur + length > bufEnd )
return buffer; return buffer;
memcpy(bufCur, bufCur - info.offset - 1, length); memcpy( bufCur, bufCur - info.offset - 1, length );
bufCur += length; bufCur += length;
} }
else else
{ {
*bufCur = *inBuf; *bufCur = *inBuf;
++inBuf; ++inBuf;
++bufCur; ++bufCur;
} }
flags <<= 1; flags <<= 1;
} }
} }
size = uncSize; size = uncSize;
return buffer; return buffer;
} }
const u8 *LoadBannerSound(const u8 *discid, u32 *size) const u8 *LoadBannerSound( const u8 *discid, u32 *size )
{ {
if(!discid) if ( !discid )
return NULL; return NULL;
Disc_SetUSB(NULL); Disc_SetUSB( NULL );
wbfs_disc_t *disc = WBFS_OpenDisc((u8 *) discid); wbfs_disc_t *disc = WBFS_OpenDisc( ( u8 * ) discid );
if(!disc) if ( !disc )
{ {
// WindowPrompt(tr("Can't find disc"), 0, tr("OK")); // WindowPrompt(tr("Can't find disc"), 0, tr("OK"));
return NULL; return NULL;
} }
wiidisc_t *wdisc = wd_open_disc((int (*)(void *, u32, u32, void *))wbfs_disc_read, disc); wiidisc_t *wdisc = wd_open_disc( ( int ( * )( void *, u32, u32, void * ) )wbfs_disc_read, disc );
if(!wdisc) if ( !wdisc )
{ {
//WindowPrompt(tr("Could not open Disc"), 0, tr("OK")); //WindowPrompt(tr("Could not open Disc"), 0, tr("OK"));
return NULL; return NULL;
} }
u8 * opening_bnr = wd_extract_file(wdisc, ALL_PARTITIONS, (char *) "opening.bnr"); u8 * opening_bnr = wd_extract_file( wdisc, ALL_PARTITIONS, ( char * ) "opening.bnr" );
if(!opening_bnr) if ( !opening_bnr )
{ {
//WindowPrompt(tr("ERROR"), tr("Failed to extract opening.bnr"), tr("OK")); //WindowPrompt(tr("ERROR"), tr("Failed to extract opening.bnr"), tr("OK"));
return NULL; return NULL;
} }
wd_close_disc(wdisc); wd_close_disc( wdisc );
WBFS_CloseDisc(disc); WBFS_CloseDisc( disc );
const U8Entry *fst; const U8Entry *fst;
const IMETHeader *imetHdr = (IMETHeader *)opening_bnr; const IMETHeader *imetHdr = ( IMETHeader * )opening_bnr;
if ( imetHdr->fcc != 0x494D4554 /*"IMET"*/ ) if ( imetHdr->fcc != 0x494D4554 /*"IMET"*/ )
{ {
// WindowPrompt(tr("IMET Header wrong."), 0, tr("OK")); // WindowPrompt(tr("IMET Header wrong."), 0, tr("OK"));
free(opening_bnr); free( opening_bnr );
return NULL; return NULL;
} }
const U8Header *bnrArcHdr = (U8Header *)(imetHdr + 1); const U8Header *bnrArcHdr = ( U8Header * )( imetHdr + 1 );
fst = (const U8Entry *)( ((const u8 *)bnrArcHdr) + bnrArcHdr->rootNodeOffset); fst = ( const U8Entry * )( ( ( const u8 * )bnrArcHdr ) + bnrArcHdr->rootNodeOffset );
u32 i; u32 i;
for (i = 1; i < fst[0].numEntries; ++i) for ( i = 1; i < fst[0].numEntries; ++i )
if (fst[i].fileType == 0 && strcasecmp(u8Filename(fst, i), "sound.bin") == 0) if ( fst[i].fileType == 0 && strcasecmp( u8Filename( fst, i ), "sound.bin" ) == 0 )
break; break;
if (i >= fst[0].numEntries) if ( i >= fst[0].numEntries )
{ {
/* Not all games have a sound.bin and this message is annoying **/ /* Not all games have a sound.bin and this message is annoying **/
//WindowPrompt(tr("sound.bin not found."), 0, tr("OK")); //WindowPrompt(tr("sound.bin not found."), 0, tr("OK"));
free(opening_bnr); free( opening_bnr );
return NULL; return NULL;
} }
const u8 *sound_bin = ((const u8 *)bnrArcHdr) + fst[i].fileOffset; const u8 *sound_bin = ( ( const u8 * )bnrArcHdr ) + fst[i].fileOffset;
if ( ((IMD5Header *)sound_bin)->fcc != 0x494D4435 /*"IMD5"*/ ) if ( ( ( IMD5Header * )sound_bin )->fcc != 0x494D4435 /*"IMD5"*/ )
{ {
// WindowPrompt(tr("IMD5 Header not right."), 0, tr("OK")); // WindowPrompt(tr("IMD5 Header not right."), 0, tr("OK"));
free(opening_bnr); free( opening_bnr );
return NULL; return NULL;
} }
const u8 *soundChunk = sound_bin + sizeof (IMD5Header);; const u8 *soundChunk = sound_bin + sizeof ( IMD5Header );;
u32 soundChunkSize = fst[i].fileLength - sizeof (IMD5Header); u32 soundChunkSize = fst[i].fileLength - sizeof ( IMD5Header );
if ( *((u32*)soundChunk) == 0x4C5A3737 /*"LZ77"*/ ) if ( *( ( u32* )soundChunk ) == 0x4C5A3737 /*"LZ77"*/ )
{ {
u32 uncSize = NULL; u32 uncSize = NULL;
u8 * uncompressed_data = uncompressLZ77(soundChunk, soundChunkSize, uncSize); u8 * uncompressed_data = uncompressLZ77( soundChunk, soundChunkSize, uncSize );
if (!uncompressed_data) if ( !uncompressed_data )
{ {
// WindowPrompt(tr("Can't decompress LZ77"), 0, tr("OK")); // WindowPrompt(tr("Can't decompress LZ77"), 0, tr("OK"));
free(opening_bnr); free( opening_bnr );
return NULL; return NULL;
} }
if(size) *size=uncSize; if ( size ) *size = uncSize;
free(opening_bnr); free( opening_bnr );
return uncompressed_data; return uncompressed_data;
} }
u8 *out = new(std::nothrow) u8[soundChunkSize]; u8 *out = new( std::nothrow ) u8[soundChunkSize];
if(out) if ( out )
{ {
memcpy(out, soundChunk, soundChunkSize); memcpy( out, soundChunk, soundChunkSize );
if(size) *size=soundChunkSize; if ( size ) *size = soundChunkSize;
} }
free(opening_bnr); free( opening_bnr );
return out; return out;
} }

View File

@ -1,6 +1,6 @@
#ifndef BANNERSOUND_H #ifndef BANNERSOUND_H
#define BANNERSOUND_H #define BANNERSOUND_H
const u8 *LoadBannerSound(const u8 *discid, u32 *size); const u8 *LoadBannerSound( const u8 *discid, u32 *size );
#endif /* BANNERSOUND_H */ #endif /* BANNERSOUND_H */

View File

@ -23,143 +23,160 @@ extern GuiWindow * mainWindow;
/**************************************************************************** /****************************************************************************
* CheatMenu * CheatMenu
***************************************************************************/ ***************************************************************************/
int CheatMenu(const char * gameID) { int CheatMenu( const char * gameID )
int choice = 0; {
bool exit = false; int choice = 0;
int ret = 1; bool exit = false;
int ret = 1;
// because destroy GuiSound must wait while sound playing is finished, we use a global sound // because destroy GuiSound must wait while sound playing is finished, we use a global sound
if(!btnClick2) btnClick2=new GuiSound(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume); if ( !btnClick2 ) btnClick2 = new GuiSound( button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume );
// GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume); // GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume);
char imgPath[100]; char imgPath[100];
snprintf(imgPath, sizeof(imgPath), "%sbutton_dialogue_box.png", CFG.theme_path); snprintf( imgPath, sizeof( imgPath ), "%sbutton_dialogue_box.png", CFG.theme_path );
GuiImageData btnOutline(imgPath, button_dialogue_box_png); GuiImageData btnOutline( imgPath, button_dialogue_box_png );
snprintf(imgPath, sizeof(imgPath), "%ssettings_background.png", CFG.theme_path); snprintf( imgPath, sizeof( imgPath ), "%ssettings_background.png", CFG.theme_path );
GuiImageData settingsbg(imgPath, settings_background_png); GuiImageData settingsbg( imgPath, settings_background_png );
GuiImage settingsbackground(&settingsbg); GuiImage settingsbackground( &settingsbg );
GuiTrigger trigA; GuiTrigger trigA;
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); trigA.SetSimpleTrigger( -1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A );
GuiTrigger trigB; GuiTrigger trigB;
trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); trigB.SetButtonOnlyTrigger( -1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B );
GuiText backBtnTxt(tr("Back") , 22, THEME.prompttext); GuiText backBtnTxt( tr( "Back" ) , 22, THEME.prompttext );
backBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); backBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 );
GuiImage backBtnImg(&btnOutline); GuiImage backBtnImg( &btnOutline );
GuiButton backBtn(&backBtnImg,&backBtnImg, 2, 3, -140, 400, &trigA, NULL, btnClick2,1); GuiButton backBtn( &backBtnImg, &backBtnImg, 2, 3, -140, 400, &trigA, NULL, btnClick2, 1 );
backBtn.SetLabel(&backBtnTxt); backBtn.SetLabel( &backBtnTxt );
backBtn.SetTrigger(&trigB); backBtn.SetTrigger( &trigB );
GuiText createBtnTxt(tr("Create") , 22, THEME.prompttext); GuiText createBtnTxt( tr( "Create" ) , 22, THEME.prompttext );
createBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); createBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 );
GuiImage createBtnImg(&btnOutline); GuiImage createBtnImg( &btnOutline );
GuiButton createBtn(&createBtnImg,&createBtnImg, 2, 3, 160, 400, &trigA, NULL, btnClick2,1); GuiButton createBtn( &createBtnImg, &createBtnImg, 2, 3, 160, 400, &trigA, NULL, btnClick2, 1 );
createBtn.SetLabel(&createBtnTxt); createBtn.SetLabel( &createBtnTxt );
char txtfilename[55]; char txtfilename[55];
snprintf(txtfilename,sizeof(txtfilename),"%s%s.txt",Settings.TxtCheatcodespath,gameID); snprintf( txtfilename, sizeof( txtfilename ), "%s%s.txt", Settings.TxtCheatcodespath, gameID );
GCTCheats c; GCTCheats c;
int check = c.openTxtfile(txtfilename); int check = c.openTxtfile( txtfilename );
int download =0; int download = 0;
switch (check) { switch ( check )
case -1: {
WindowPrompt(tr("Error"),tr("Cheatfile is blank"),tr("OK")); case -1:
break; WindowPrompt( tr( "Error" ), tr( "Cheatfile is blank" ), tr( "OK" ) );
case 0: break;
download = WindowPrompt(tr("Error"),tr("No Cheatfile found"),tr("Download Now"),tr("Cancel")); case 0:
if (download==1) download = WindowPrompt( tr( "Error" ), tr( "No Cheatfile found" ), tr( "Download Now" ), tr( "Cancel" ) );
{ if ( download == 1 )
download = CodeDownload(gameID); {
if(download < 0 || c.openTxtfile(txtfilename) != 1) download = CodeDownload( gameID );
break; if ( download < 0 || c.openTxtfile( txtfilename ) != 1 )
} break;
else }
break; else
case 1: break;
int cntcheats = c.getCnt(); case 1:
customOptionList cheatslst(cntcheats); int cntcheats = c.getCnt();
GuiCustomOptionBrowser chtBrowser(400, 280, &cheatslst, CFG.theme_path, "bg_options_settings.png", bg_options_settings_png, 1, 90); customOptionList cheatslst( cntcheats );
chtBrowser.SetPosition(0, 90); GuiCustomOptionBrowser chtBrowser( 400, 280, &cheatslst, CFG.theme_path, "bg_options_settings.png", bg_options_settings_png, 1, 90 );
chtBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); chtBrowser.SetPosition( 0, 90 );
chtBrowser.SetClickable(true); chtBrowser.SetAlignment( ALIGN_CENTRE, ALIGN_TOP );
chtBrowser.SetClickable( true );
GuiText titleTxt(c.getGameName().c_str(), 28, (GXColor) {0, 0, 0, 255}); GuiText titleTxt( c.getGameName().c_str(), 28, ( GXColor ) {0, 0, 0, 255} );
titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); titleTxt.SetAlignment( ALIGN_CENTRE, ALIGN_TOP );
titleTxt.SetMaxWidth(350, SCROLL_HORIZONTAL); titleTxt.SetMaxWidth( 350, SCROLL_HORIZONTAL );
titleTxt.SetPosition(12,40); titleTxt.SetPosition( 12, 40 );
for (int i = 0; i <= cntcheats; i++) { for ( int i = 0; i <= cntcheats; i++ )
cheatslst.SetValue(i, "%s",c.getCheatName(i).c_str()); {
cheatslst.SetName(i, "OFF"); cheatslst.SetValue( i, "%s", c.getCheatName( i ).c_str() );
} cheatslst.SetName( i, "OFF" );
}
HaltGui(); HaltGui();
GuiWindow w(screenwidth, screenheight); GuiWindow w( screenwidth, screenheight );
w.Append(&settingsbackground); w.Append( &settingsbackground );
w.Append(&titleTxt); w.Append( &titleTxt );
w.Append(&backBtn); w.Append( &backBtn );
w.Append(&createBtn); w.Append( &createBtn );
w.Append(&chtBrowser); w.Append( &chtBrowser );
mainWindow->SetState(STATE_DISABLED); mainWindow->SetState( STATE_DISABLED );
mainWindow->ChangeFocus(&w); mainWindow->ChangeFocus( &w );
mainWindow->Append(&w); mainWindow->Append( &w );
ResumeGui(); ResumeGui();
while (!exit) { while ( !exit )
VIDEO_WaitVSync (); {
VIDEO_WaitVSync ();
ret = chtBrowser.GetClickedOption(); ret = chtBrowser.GetClickedOption();
if (ret != -1) { if ( ret != -1 )
const char *strCheck = cheatslst.GetName(ret); {
if (strncmp(strCheck,"ON",2) == 0) { const char *strCheck = cheatslst.GetName( ret );
cheatslst.SetName(ret,"%s","OFF"); if ( strncmp( strCheck, "ON", 2 ) == 0 )
} else if (strncmp(strCheck,"OFF",3) == 0) { {
cheatslst.SetName(ret,"%s","ON"); cheatslst.SetName( ret, "%s", "OFF" );
} }
} else if ( strncmp( strCheck, "OFF", 3 ) == 0 )
{
cheatslst.SetName( ret, "%s", "ON" );
}
}
if (createBtn.GetState() == STATE_CLICKED) { if ( createBtn.GetState() == STATE_CLICKED )
createBtn.ResetState(); {
if (cntcheats > 0) { createBtn.ResetState();
int selectednrs[30]; if ( cntcheats > 0 )
int x = 0; {
for (int i = 0; i <= cntcheats; i++) { int selectednrs[30];
const char *strCheck = cheatslst.GetName(i); int x = 0;
if (strncmp(strCheck,"ON",2) == 0) { for ( int i = 0; i <= cntcheats; i++ )
selectednrs[x] = i; {
x++; const char *strCheck = cheatslst.GetName( i );
} if ( strncmp( strCheck, "ON", 2 ) == 0 )
} {
if (x == 0) { selectednrs[x] = i;
WindowPrompt(tr("Error"),tr("No cheats were selected"),tr("OK")); x++;
} else { }
subfoldercreate(Settings.Cheatcodespath); }
string chtpath = Settings.Cheatcodespath; if ( x == 0 )
string gctfname = chtpath + c.getGameID() + ".gct"; {
c.createGCT(selectednrs,x,gctfname.c_str()); WindowPrompt( tr( "Error" ), tr( "No cheats were selected" ), tr( "OK" ) );
WindowPrompt(tr("GCT File created"),NULL,tr("OK")); }
exit = true; else
break; {
} subfoldercreate( Settings.Cheatcodespath );
} else WindowPrompt(tr("Error"),tr("Could not create GCT file"),tr("OK")); string chtpath = Settings.Cheatcodespath;
} string gctfname = chtpath + c.getGameID() + ".gct";
c.createGCT( selectednrs, x, gctfname.c_str() );
WindowPrompt( tr( "GCT File created" ), NULL, tr( "OK" ) );
exit = true;
break;
}
}
else WindowPrompt( tr( "Error" ), tr( "Could not create GCT file" ), tr( "OK" ) );
}
if (backBtn.GetState() == STATE_CLICKED) { if ( backBtn.GetState() == STATE_CLICKED )
backBtn.ResetState(); {
exit = true; backBtn.ResetState();
break; exit = true;
} break;
} }
HaltGui(); }
mainWindow->SetState(STATE_DEFAULT); HaltGui();
mainWindow->Remove(&w); mainWindow->SetState( STATE_DEFAULT );
ResumeGui(); mainWindow->Remove( &w );
break; ResumeGui();
} break;
}
return choice; return choice;
} }

View File

@ -8,6 +8,6 @@
#ifndef _CHEATMENU_H_ #ifndef _CHEATMENU_H_
#define _CHEATMENU_H_ #define _CHEATMENU_H_
int CheatMenu(const char * gameID); int CheatMenu( const char * gameID );
#endif #endif

View File

@ -12,96 +12,116 @@
#define ERRORRANGE "Error: CheatNr out of range" #define ERRORRANGE "Error: CheatNr out of range"
GCTCheats::GCTCheats(void) { GCTCheats::GCTCheats( void )
{
iCntCheats = 0; iCntCheats = 0;
} }
GCTCheats::~GCTCheats(void) { GCTCheats::~GCTCheats( void )
{
string sGameID =""; string sGameID = "";
string sGameTitle = ""; string sGameTitle = "";
/*string sCheatName[MAXCHEATS]; /*string sCheatName[MAXCHEATS];
string sCheats[MAXCHEATS]; string sCheats[MAXCHEATS];
string sCheatComment[MAXCHEATS];*/ string sCheatComment[MAXCHEATS];*/
} }
int GCTCheats::getCnt() { int GCTCheats::getCnt()
{
return iCntCheats; return iCntCheats;
} }
string GCTCheats::getGameName(void) { string GCTCheats::getGameName( void )
{
return sGameTitle; return sGameTitle;
} }
string GCTCheats::getGameID(void) { string GCTCheats::getGameID( void )
{
return sGameID; return sGameID;
} }
string GCTCheats::getCheat(int nr) { string GCTCheats::getCheat( int nr )
if (nr <= (iCntCheats-1)) { {
if ( nr <= ( iCntCheats - 1 ) )
{
return sCheats[nr]; return sCheats[nr];
} else { }
else
{
return ERRORRANGE; return ERRORRANGE;
} }
} }
string GCTCheats::getCheatName(int nr) { string GCTCheats::getCheatName( int nr )
if (nr <= (iCntCheats-1)) { {
if ( nr <= ( iCntCheats - 1 ) )
{
return sCheatName[nr]; return sCheatName[nr];
} else { }
else
{
return ERRORRANGE; return ERRORRANGE;
} }
} }
string GCTCheats::getCheatComment(int nr) { string GCTCheats::getCheatComment( int nr )
if (nr <= (iCntCheats-1)) { {
if ( nr <= ( iCntCheats - 1 ) )
{
return sCheatComment[nr]; return sCheatComment[nr];
} else { }
else
{
return ERRORRANGE; return ERRORRANGE;
} }
} }
int GCTCheats::createGCT(int nr,const char * filename) { int GCTCheats::createGCT( int nr, const char * filename )
{
if (nr == 0) if ( nr == 0 )
return 0; return 0;
ofstream filestr; ofstream filestr;
filestr.open(filename); filestr.open( filename );
if (filestr.fail()) if ( filestr.fail() )
return 0; return 0;
//Header and Footer //Header and Footer
char header[] = { 0x00, 0xd0, 0xc0, 0xde, 0x00, 0xd0, 0xc0, 0xde}; char header[] = { 0x00, 0xd0, 0xc0, 0xde, 0x00, 0xd0, 0xc0, 0xde};
char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
string buf = getCheat(nr); string buf = getCheat( nr );
filestr.write(header,sizeof(header)); filestr.write( header, sizeof( header ) );
int x = 0; int x = 0;
long int li; long int li;
int len = buf.size(); int len = buf.size();
while (x < len) { while ( x < len )
string temp = buf.substr(x,2); {
li = strtol(temp.c_str(),NULL,16); string temp = buf.substr( x, 2 );
li = strtol( temp.c_str(), NULL, 16 );
temp = li; temp = li;
filestr.write(temp.c_str(),1); filestr.write( temp.c_str(), 1 );
x +=2; x += 2;
} }
filestr.write(footer,sizeof(footer)); filestr.write( footer, sizeof( footer ) );
filestr.close(); filestr.close();
return 1; return 1;
} }
int GCTCheats::createGCT(const char * chtbuffer,const char * filename) { int GCTCheats::createGCT( const char * chtbuffer, const char * filename )
{
ofstream filestr; ofstream filestr;
filestr.open(filename); filestr.open( filename );
if (filestr.fail()) if ( filestr.fail() )
return 0; return 0;
//Header and Footer //Header and Footer
@ -109,146 +129,162 @@ int GCTCheats::createGCT(const char * chtbuffer,const char * filename) {
char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
string buf = chtbuffer; string buf = chtbuffer;
filestr.write(header,sizeof(header)); filestr.write( header, sizeof( header ) );
int x = 0; int x = 0;
long int li; long int li;
int len = buf.size(); int len = buf.size();
while (x < len) { while ( x < len )
string temp = buf.substr(x,2); {
li = strtol(temp.c_str(),NULL,16); string temp = buf.substr( x, 2 );
li = strtol( temp.c_str(), NULL, 16 );
temp = li; temp = li;
filestr.write(temp.c_str(),1); filestr.write( temp.c_str(), 1 );
x +=2; x += 2;
} }
filestr.write(footer,sizeof(footer)); filestr.write( footer, sizeof( footer ) );
filestr.close(); filestr.close();
return 1; return 1;
} }
int GCTCheats::createGCT(int nr[],int cnt,const char * filename) { int GCTCheats::createGCT( int nr[], int cnt, const char * filename )
{
if (cnt == 0) if ( cnt == 0 )
return 0; return 0;
ofstream filestr; ofstream filestr;
filestr.open(filename); filestr.open( filename );
if (filestr.fail()) if ( filestr.fail() )
return 0; return 0;
//Header and Footer //Header and Footer
char header[] = { 0x00, 0xd0, 0xc0, 0xde, 0x00, 0xd0, 0xc0, 0xde}; char header[] = { 0x00, 0xd0, 0xc0, 0xde, 0x00, 0xd0, 0xc0, 0xde};
char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; char footer[] = { 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
filestr.write(header,sizeof(header)); filestr.write( header, sizeof( header ) );
int c = 0; int c = 0;
while (c != cnt) { while ( c != cnt )
{
int actnr = nr[c]; int actnr = nr[c];
string buf = getCheat(actnr); string buf = getCheat( actnr );
long int li; long int li;
int len = buf.size(); int len = buf.size();
int x = 0; int x = 0;
while (x < len) { while ( x < len )
string temp = buf.substr(x,2); {
li = strtol(temp.c_str(),NULL,16); string temp = buf.substr( x, 2 );
li = strtol( temp.c_str(), NULL, 16 );
temp = li; temp = li;
filestr.write(temp.c_str(),1); filestr.write( temp.c_str(), 1 );
x +=2; x += 2;
} }
c++; c++;
} }
filestr.write(footer,sizeof(footer)); filestr.write( footer, sizeof( footer ) );
filestr.close(); filestr.close();
return 1; return 1;
} }
int GCTCheats::openTxtfile(const char * filename) { int GCTCheats::openTxtfile( const char * filename )
{
ifstream filestr; ifstream filestr;
int i = 0; int i = 0;
string str; string str;
filestr.open(filename); filestr.open( filename );
if (filestr.fail()) if ( filestr.fail() )
return 0; return 0;
filestr.seekg(0,ios_base::end); filestr.seekg( 0, ios_base::end );
int size = filestr.tellg(); int size = filestr.tellg();
if (size <= 0) return -1; if ( size <= 0 ) return -1;
filestr.seekg(0,ios_base::beg); filestr.seekg( 0, ios_base::beg );
getline(filestr,sGameID); getline( filestr, sGameID );
if (sGameID[sGameID.length() - 1] == '\r') if ( sGameID[sGameID.length() - 1] == '\r' )
sGameID.erase(sGameID.length() - 1); sGameID.erase( sGameID.length() - 1 );
getline(filestr,sGameTitle); getline( filestr, sGameTitle );
if (sGameTitle[sGameTitle.length() - 1] == '\r') if ( sGameTitle[sGameTitle.length() - 1] == '\r' )
sGameTitle.erase(sGameTitle.length() - 1); sGameTitle.erase( sGameTitle.length() - 1 );
getline(filestr,sCheatName[i]); // skip first line if file uses CRLF getline( filestr, sCheatName[i] ); // skip first line if file uses CRLF
if (!sGameTitle[sGameTitle.length() - 1] == '\r') if ( !sGameTitle[sGameTitle.length() - 1] == '\r' )
filestr.seekg(0,ios_base::beg); filestr.seekg( 0, ios_base::beg );
while (!filestr.eof()) { while ( !filestr.eof() )
getline(filestr,sCheatName[i]); // '\n' delimiter by default {
if (sCheatName[i][sCheatName[i].length() - 1] == '\r') getline( filestr, sCheatName[i] ); // '\n' delimiter by default
sCheatName[i].erase(sCheatName[i].length() - 1); if ( sCheatName[i][sCheatName[i].length() - 1] == '\r' )
sCheatName[i].erase( sCheatName[i].length() - 1 );
string cheatdata; string cheatdata;
bool emptyline = false; bool emptyline = false;
do { do
getline(filestr,str); {
if (str[str.length() - 1] == '\r') getline( filestr, str );
str.erase(str.length() - 1); if ( str[str.length() - 1] == '\r' )
str.erase( str.length() - 1 );
if (str == "" || str[0] == '\r' || str[0] == '\n') { if ( str == "" || str[0] == '\r' || str[0] == '\n' )
{
emptyline = true; emptyline = true;
break; break;
} }
if (IsCode(str)) { if ( IsCode( str ) )
// remove any garbage (comment) after code {
while (str.size() > 17) { // remove any garbage (comment) after code
str.erase(str.length() - 1); while ( str.size() > 17 )
} {
cheatdata.append(str); str.erase( str.length() - 1 );
size_t found=cheatdata.find(' '); }
cheatdata.replace(found,1,""); cheatdata.append( str );
} else { size_t found = cheatdata.find( ' ' );
cheatdata.replace( found, 1, "" );
}
else
{
//printf("%i",str.size()); //printf("%i",str.size());
sCheatComment[i] = str; sCheatComment[i] = str;
} }
if (filestr.eof()) break; if ( filestr.eof() ) break;
} while (!emptyline); }
while ( !emptyline );
sCheats[i] = cheatdata; sCheats[i] = cheatdata;
i++; i++;
if (i == MAXCHEATS) break; if ( i == MAXCHEATS ) break;
} }
iCntCheats = i; iCntCheats = i;
filestr.close(); filestr.close();
return 1; return 1;
} }
bool GCTCheats::IsCode(const std::string& str) { bool GCTCheats::IsCode( const std::string& str )
if (str[8] == ' ' && str.size() >= 17) { {
// accept strings longer than 17 in case there is a comment on the same line as the code if ( str[8] == ' ' && str.size() >= 17 )
char part1[9]; {
char part2[9]; // accept strings longer than 17 in case there is a comment on the same line as the code
snprintf(part1,sizeof(part1),"%c%c%c%c%c%c%c%c",str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7]); char part1[9];
snprintf(part2,sizeof(part2),"%c%c%c%c%c%c%c%c",str[9],str[10],str[11],str[12],str[13],str[14],str[15],str[16]); char part2[9];
if ((strtok(part1,"0123456789ABCDEFabcdef") == NULL) && (strtok(part2,"0123456789ABCDEFabcdef") == NULL)) { snprintf( part1, sizeof( part1 ), "%c%c%c%c%c%c%c%c", str[0], str[1], str[2], str[3], str[4], str[5], str[6], str[7] );
return true; snprintf( part2, sizeof( part2 ), "%c%c%c%c%c%c%c%c", str[9], str[10], str[11], str[12], str[13], str[14], str[15], str[16] );
} if ( ( strtok( part1, "0123456789ABCDEFabcdef" ) == NULL ) && ( strtok( part2, "0123456789ABCDEFabcdef" ) == NULL ) )
} {
return false; return true;
}
}
return false;
} }

View File

@ -1,7 +1,7 @@
/* /*
* gct.h * gct.h
* Class to handle Ocarina TXT Cheatfiles * Class to handle Ocarina TXT Cheatfiles
* *
*/ */
#ifndef _GCT_H #ifndef _GCT_H
@ -14,61 +14,62 @@
using namespace std; using namespace std;
//!Handles Ocarina TXT Cheatfiles //!Handles Ocarina TXT Cheatfiles
class GCTCheats { class GCTCheats
private: {
string sGameID; private:
string sGameTitle; string sGameID;
string sCheatName[MAXCHEATS]; string sGameTitle;
string sCheats[MAXCHEATS]; string sCheatName[MAXCHEATS];
string sCheatComment[MAXCHEATS]; string sCheats[MAXCHEATS];
int iCntCheats; string sCheatComment[MAXCHEATS];
int iCntCheats;
public: public:
//!Constructor //!Constructor
GCTCheats(void); GCTCheats( void );
//!Destructor //!Destructor
~GCTCheats(void); ~GCTCheats( void );
//!Open txt file with cheats //!Open txt file with cheats
//!\param filename name of TXT file //!\param filename name of TXT file
//!\return error code //!\return error code
int openTxtfile(const char * filename); int openTxtfile( const char * filename );
//!Creates GCT file for one cheat //!Creates GCT file for one cheat
//!\param nr selected Cheat Numbers //!\param nr selected Cheat Numbers
//!\param filename name of GCT file //!\param filename name of GCT file
//!\return error code //!\return error code
int createGCT(int nr,const char * filename); int createGCT( int nr, const char * filename );
//!Creates GCT file from a buffer //!Creates GCT file from a buffer
//!\param chtbuffer buffer that holds the cheat data //!\param chtbuffer buffer that holds the cheat data
//!\param filename name of GCT file //!\param filename name of GCT file
//!\return error code //!\return error code
int createGCT(const char * chtbuffer,const char * filename); int createGCT( const char * chtbuffer, const char * filename );
//!Creates GCT file //!Creates GCT file
//!\param nr[] array of selected Cheat Numbers //!\param nr[] array of selected Cheat Numbers
//!\param cnt size of array //!\param cnt size of array
//!\param filename name of GCT file //!\param filename name of GCT file
//!\return error code //!\return error code
int createGCT(int nr[],int cnt,const char * filename); int createGCT( int nr[], int cnt, const char * filename );
//!Gets Count cheats //!Gets Count cheats
//!\return Count cheats //!\return Count cheats
int getCnt(); int getCnt();
//!Gets Game Name //!Gets Game Name
//!\return Game Name //!\return Game Name
string getGameName(void); string getGameName( void );
//!Gets GameID //!Gets GameID
//!\return GameID //!\return GameID
string getGameID(void); string getGameID( void );
//!Gets cheat data //!Gets cheat data
//!\return cheat data //!\return cheat data
string getCheat(int nr); string getCheat( int nr );
//!Gets Cheat Name //!Gets Cheat Name
//!\return Cheat Name //!\return Cheat Name
string getCheatName(int nr); string getCheatName( int nr );
//!Gets Cheat Comment //!Gets Cheat Comment
//!\return Cheat Comment //!\return Cheat Comment
string getCheatComment(int nr); string getCheatComment( int nr );
//!Check if string is a code //!Check if string is a code
//!\return true/false //!\return true/false
bool IsCode(const std::string& s); bool IsCode( const std::string& s );
}; };
#endif /* _GCT_H */ #endif /* _GCT_H */

View File

@ -44,198 +44,219 @@ sec_t fat_wbfs_sec = 0;
int fs_ntfs_mount = 0; int fs_ntfs_mount = 0;
sec_t fs_ntfs_sec = 0; sec_t fs_ntfs_sec = 0;
int USBDevice_Init() { int USBDevice_Init()
{
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf("\nUSBDevice_Init()"); gprintf( "\nUSBDevice_Init()" );
#endif #endif
//closing all open Files write back the cache and then shutdown em! //closing all open Files write back the cache and then shutdown em!
fatUnmount("USB:/"); fatUnmount( "USB:/" );
//right now mounts first FAT-partition //right now mounts first FAT-partition
//try first mount with cIOS //try first mount with cIOS
// if (!fatMount("USB", &__io_wiiums, 0, CACHE, SECTORS)) { // if (!fatMount("USB", &__io_wiiums, 0, CACHE, SECTORS)) {
// //try now mount with libogc // //try now mount with libogc
if (!fatMount("USB", &__io_usbstorage2, 0, CACHE, SECTORS)) { if ( !fatMount( "USB", &__io_usbstorage2, 0, CACHE, SECTORS ) )
{
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf(":-1"); gprintf( ":-1" );
#endif #endif
return -1; return -1;
} }
// } // }
fat_usb_mount = 1; fat_usb_mount = 1;
fat_usb_sec = _FAT_startSector; fat_usb_sec = _FAT_startSector;
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf(":0"); gprintf( ":0" );
#endif #endif
return 0; return 0;
} }
void USBDevice_deInit() { void USBDevice_deInit()
{
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf("\nUSBDevice_deInit()"); gprintf( "\nUSBDevice_deInit()" );
#endif #endif
//closing all open Files write back the cache and then shutdown em! //closing all open Files write back the cache and then shutdown em!
fatUnmount("USB:/"); fatUnmount( "USB:/" );
fat_usb_mount = 0; fat_usb_mount = 0;
fat_usb_sec = 0; fat_usb_sec = 0;
} }
int WBFSDevice_Init(u32 sector) { int WBFSDevice_Init( u32 sector )
{
//closing all open Files write back the cache and then shutdown em! //closing all open Files write back the cache and then shutdown em!
fatUnmount("WBFS:/"); fatUnmount( "WBFS:/" );
//right now mounts first FAT-partition //right now mounts first FAT-partition
//try first mount with cIOS //try first mount with cIOS
// if (!fatMount("WBFS", &__io_wiiums, 0, CACHE, SECTORS)) { // if (!fatMount("WBFS", &__io_wiiums, 0, CACHE, SECTORS)) {
//try now mount with libogc //try now mount with libogc
if (!fatMount("WBFS", &__io_usbstorage2, 0, CACHE, SECTORS)) { if ( !fatMount( "WBFS", &__io_usbstorage2, 0, CACHE, SECTORS ) )
return -1; {
} return -1;
// } }
// }
fat_wbfs_mount = 1; fat_wbfs_mount = 1;
fat_wbfs_sec = _FAT_startSector; fat_wbfs_sec = _FAT_startSector;
if (sector && fat_wbfs_sec != sector) { if ( sector && fat_wbfs_sec != sector )
// This is an error situation...actually, but is ignored in Config loader also {
// Should ask Oggzee about it... // This is an error situation...actually, but is ignored in Config loader also
} // Should ask Oggzee about it...
return 0; }
return 0;
} }
void WBFSDevice_deInit() { void WBFSDevice_deInit()
{
//closing all open Files write back the cache and then shutdown em! //closing all open Files write back the cache and then shutdown em!
fatUnmount("WBFS:/"); fatUnmount( "WBFS:/" );
fat_wbfs_mount = 0; fat_wbfs_mount = 0;
fat_wbfs_sec = 0; fat_wbfs_sec = 0;
} }
int isInserted(const char *path) { int isInserted( const char *path )
if (!strncmp(path, "USB:", 4)) {
if ( !strncmp( path, "USB:", 4 ) )
return 1; return 1;
return __io_sdhc.isInserted() || __io_wiisd.isInserted(); return __io_sdhc.isInserted() || __io_wiisd.isInserted();
} }
int SDCard_Init() { int SDCard_Init()
{
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf("\nSDCard_Init()"); gprintf( "\nSDCard_Init()" );
#endif #endif
//closing all open Files write back the cache and then shutdown em! //closing all open Files write back the cache and then shutdown em!
fatUnmount("SD:/"); fatUnmount( "SD:/" );
//right now mounts first FAT-partition //right now mounts first FAT-partition
if (fatMount("SD", &__io_wiisd, 0, CACHE, SECTORS)) { if ( fatMount( "SD", &__io_wiisd, 0, CACHE, SECTORS ) )
fat_sd_mount = MOUNT_SD; {
fat_sd_sec = _FAT_startSector; fat_sd_mount = MOUNT_SD;
fat_sd_sec = _FAT_startSector;
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf(":1"); gprintf( ":1" );
#endif #endif
return 1; return 1;
} }
else if (fatMount("SD", &__io_sdhc, 0, CACHE, SDHC_SECTOR_SIZE)) { else if ( fatMount( "SD", &__io_sdhc, 0, CACHE, SDHC_SECTOR_SIZE ) )
fat_sd_mount = MOUNT_SDHC; {
fat_sd_sec = _FAT_startSector; fat_sd_mount = MOUNT_SDHC;
fat_sd_sec = _FAT_startSector;
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf(":1"); gprintf( ":1" );
#endif #endif
return 1; return 1;
} }
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf(":-1"); gprintf( ":-1" );
#endif #endif
return -1; return -1;
} }
void SDCard_deInit() { void SDCard_deInit()
{
#ifdef DEBUG_FAT #ifdef DEBUG_FAT
gprintf("\nSDCard_deInit()"); gprintf( "\nSDCard_deInit()" );
#endif #endif
//closing all open Files write back the cache and then shutdown em! //closing all open Files write back the cache and then shutdown em!
fatUnmount("SD:/"); fatUnmount( "SD:/" );
fat_sd_mount = MOUNT_NONE; fat_sd_mount = MOUNT_NONE;
fat_sd_sec = 0; fat_sd_sec = 0;
} }
void ntfsInit(); void ntfsInit();
s32 MountNTFS(u32 sector) s32 MountNTFS( u32 sector )
{ {
s32 ret; s32 ret;
if (fs_ntfs_mount) return 0; if ( fs_ntfs_mount ) return 0;
//printf("mounting NTFS\n"); //printf("mounting NTFS\n");
//Wpad_WaitButtons(); //Wpad_WaitButtons();
_FAT_mem_init(); _FAT_mem_init();
ntfsInit(); // Call ntfs init here, to prevent locale resets ntfsInit(); // Call ntfs init here, to prevent locale resets
// ntfsInit resets locale settings // ntfsInit resets locale settings
// which breaks unicode in console // which breaks unicode in console
// so we change it back to C-UTF-8 // so we change it back to C-UTF-8
setlocale(LC_CTYPE, "C-UTF-8"); setlocale( LC_CTYPE, "C-UTF-8" );
setlocale(LC_MESSAGES, "C-UTF-8"); setlocale( LC_MESSAGES, "C-UTF-8" );
if (wbfsDev == WBFS_DEVICE_USB) { if ( wbfsDev == WBFS_DEVICE_USB )
/* Initialize WBFS interface */ {
// if (!__io_wiiums.startup()) { /* Initialize WBFS interface */
ret = __io_usbstorage2.startup(); // if (!__io_wiiums.startup()) {
if (!ret) { ret = __io_usbstorage2.startup();
return -1; if ( !ret )
} {
// } return -1;
/* Mount device */ }
// if (!ntfsMount("NTFS", &__io_wiiums, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) { // }
ret = ntfsMount("NTFS", &__io_usbstorage2, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER); /* Mount device */
if (!ret) { // if (!ntfsMount("NTFS", &__io_wiiums, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) {
return -2; ret = ntfsMount( "NTFS", &__io_usbstorage2, sector, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER );
} if ( !ret )
// } {
} else if (wbfsDev == WBFS_DEVICE_SDHC) { return -2;
if (sdhc_mode_sd == 0) { }
ret = ntfsMount("NTFS", &__io_sdhc, 0, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER); // }
} else { }
ret = ntfsMount("NTFS", &__io_sdhc, 0, CACHE, SECTORS_SD, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER); else if ( wbfsDev == WBFS_DEVICE_SDHC )
} {
if (!ret) { if ( sdhc_mode_sd == 0 )
return -5; {
} ret = ntfsMount( "NTFS", &__io_sdhc, 0, CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER );
} }
else
{
ret = ntfsMount( "NTFS", &__io_sdhc, 0, CACHE, SECTORS_SD, NTFS_SHOW_HIDDEN_FILES | NTFS_READ_ONLY | NTFS_RECOVER );
}
if ( !ret )
{
return -5;
}
}
fs_ntfs_mount = 1; fs_ntfs_mount = 1;
fs_ntfs_sec = sector; //_FAT_startSector; fs_ntfs_sec = sector; //_FAT_startSector;
return 0; return 0;
} }
s32 UnmountNTFS(void) s32 UnmountNTFS( void )
{ {
/* Unmount device */ /* Unmount device */
ntfsUnmount("NTFS:/", true); ntfsUnmount( "NTFS:/", true );
fs_ntfs_mount = 0; fs_ntfs_mount = 0;
fs_ntfs_sec = 0; fs_ntfs_sec = 0;
return 0; return 0;
} }
void _FAT_mem_init() void _FAT_mem_init()
{ {
} }
void* _FAT_mem_allocate(size_t size) void* _FAT_mem_allocate( size_t size )
{ {
return malloc(size); return malloc( size );
} }
void* _FAT_mem_align(size_t size) void* _FAT_mem_align( size_t size )
{ {
return memalign(32, size); return memalign( 32, size );
} }
void _FAT_mem_free(void *mem) void _FAT_mem_free( void *mem )
{ {
free(mem); free( mem );
} }

View File

@ -2,33 +2,34 @@
#define _FATMOUNTER_H_ #define _FATMOUNTER_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
extern int fat_sd_mount; extern int fat_sd_mount;
extern sec_t fat_sd_sec; extern sec_t fat_sd_sec;
extern int fat_usb_mount; extern int fat_usb_mount;
extern sec_t fat_usb_sec; extern sec_t fat_usb_sec;
extern int fat_wbfs_mount; extern int fat_wbfs_mount;
extern sec_t fat_wbfs_sec; extern sec_t fat_wbfs_sec;
int USBDevice_Init(); int USBDevice_Init();
void USBDevice_deInit(); void USBDevice_deInit();
int WBFSDevice_Init(u32 sector); int WBFSDevice_Init( u32 sector );
void WBFSDevice_deInit(); void WBFSDevice_deInit();
int isInserted(const char *path); int isInserted( const char *path );
int SDCard_Init(); int SDCard_Init();
void SDCard_deInit(); void SDCard_deInit();
s32 MountNTFS(u32 sector);
s32 UnmountNTFS(void);
extern int fat_usb_mount; s32 MountNTFS( u32 sector );
extern sec_t fat_usb_sec; s32 UnmountNTFS( void );
extern int fat_wbfs_mount;
extern sec_t fat_wbfs_sec; extern int fat_usb_mount;
extern int fs_ntfs_mount; extern sec_t fat_usb_sec;
extern sec_t fs_ntfs_sec; extern int fat_wbfs_mount;
extern sec_t fat_wbfs_sec;
extern int fs_ntfs_mount;
extern sec_t fs_ntfs_sec;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -11,23 +11,23 @@
#include <gccore.h> #include <gccore.h>
extern const u8 font_ttf[]; extern const u8 font_ttf[];
extern const u32 font_ttf_size; extern const u32 font_ttf_size;
extern const u8 clock_ttf[]; extern const u8 clock_ttf[];
extern const u32 clock_ttf_size; extern const u32 clock_ttf_size;
extern const u8 closebutton_png[]; extern const u8 closebutton_png[];
extern const u32 closebutton_png_size; extern const u32 closebutton_png_size;
extern const u8 gxlogo_png[]; extern const u8 gxlogo_png[];
extern const u32 gxlogo_png_size; extern const u32 gxlogo_png_size;
extern const u8 sdcard_png[]; extern const u8 sdcard_png[];
extern const u32 sdcard_png_size; extern const u32 sdcard_png_size;
extern const u8 sdcard_over_png[]; extern const u8 sdcard_over_png[];
extern const u32 sdcard_over_png_size; extern const u32 sdcard_over_png_size;
extern const u8 Wifi_btn_png[]; extern const u8 Wifi_btn_png[];
extern const u32 Wifi_btn_png_size; extern const u32 Wifi_btn_png_size;
@ -35,50 +35,50 @@ extern const u32 Wifi_btn_png_size;
extern const u8 Channel_btn_png[]; extern const u8 Channel_btn_png[];
extern const u32 Channel_btn_png_size; extern const u32 Channel_btn_png_size;
extern const u8 wiimote_png[]; extern const u8 wiimote_png[];
extern const u32 wiimote_png_size; extern const u32 wiimote_png_size;
extern const u8 bg_music_ogg[]; extern const u8 bg_music_ogg[];
extern const u32 bg_music_ogg_size; extern const u32 bg_music_ogg_size;
extern const u8 credits_music_ogg[]; extern const u8 credits_music_ogg[];
extern const u32 credits_music_ogg_size; extern const u32 credits_music_ogg_size;
extern const u8 gameinfo1_png[]; extern const u8 gameinfo1_png[];
extern const u32 gameinfo1_png_size; extern const u32 gameinfo1_png_size;
extern const u8 gameinfo2_png[]; extern const u8 gameinfo2_png[];
extern const u32 gameinfo2_png_size; extern const u32 gameinfo2_png_size;
extern const u8 gameinfo1a_png[]; extern const u8 gameinfo1a_png[];
extern const u32 gameinfo1a_png_size; extern const u32 gameinfo1a_png_size;
extern const u8 gameinfo2a_png[]; extern const u8 gameinfo2a_png[];
extern const u32 gameinfo2a_png_size; extern const u32 gameinfo2a_png_size;
extern const u8 menuin_ogg[]; extern const u8 menuin_ogg[];
extern const u32 menuin_ogg_size; extern const u32 menuin_ogg_size;
extern const u8 menuout_ogg[]; extern const u8 menuout_ogg[];
extern const u32 menuout_ogg_size; extern const u32 menuout_ogg_size;
extern const u8 success_ogg[]; extern const u8 success_ogg[];
extern const u32 success_ogg_size; extern const u32 success_ogg_size;
extern const u8 credits_button_png[]; extern const u8 credits_button_png[];
extern const u32 credits_button_png_size; extern const u32 credits_button_png_size;
extern const u8 credits_button_over_png[]; extern const u8 credits_button_over_png[];
extern const u32 credits_button_over_png_size; extern const u32 credits_button_over_png_size;
extern const u8 button_over_pcm[]; extern const u8 button_over_pcm[];
extern const u32 button_over_pcm_size; extern const u32 button_over_pcm_size;
extern const u8 button_click_pcm[]; extern const u8 button_click_pcm[];
extern const u32 button_click_pcm_size; extern const u32 button_click_pcm_size;
extern const u8 button_click2_pcm[]; extern const u8 button_click2_pcm[];
extern const u32 button_click2_pcm_size; extern const u32 button_click2_pcm_size;
extern const u8 tooltip_left_png[]; extern const u8 tooltip_left_png[];
extern const u32 tooltip_left_png_size; extern const u32 tooltip_left_png_size;
@ -95,11 +95,11 @@ extern const u32 startgame_arrow_left_png_size;
extern const u8 startgame_arrow_right_png[]; extern const u8 startgame_arrow_right_png[];
extern const u32 startgame_arrow_right_png_size; extern const u32 startgame_arrow_right_png_size;
extern const u8 credits_bg_png[]; extern const u8 credits_bg_png[];
extern const u32 credits_bg_png_size; extern const u32 credits_bg_png_size;
extern const u8 little_star_png[]; extern const u8 little_star_png[];
extern const u32 little_star_png_size; extern const u32 little_star_png_size;
extern const u8 background_png[]; extern const u8 background_png[];
extern const u32 background_png_size; extern const u32 background_png_size;
@ -116,29 +116,29 @@ extern const u32 settings_background_png_size;
extern const u8 bg_browser_png[]; extern const u8 bg_browser_png[];
extern const u32 bg_browser_png_size; extern const u32 bg_browser_png_size;
extern const u8 icon_archives_png[]; extern const u8 icon_archives_png[];
extern const u32 icon_archives_png_size; extern const u32 icon_archives_png_size;
//extern const u8 icon_default_png[]; //extern const u8 icon_default_png[];
//extern const u32 icon_default_png_size; //extern const u32 icon_default_png_size;
extern const u8 icon_folder_png[]; extern const u8 icon_folder_png[];
extern const u32 icon_folder_png_size; extern const u32 icon_folder_png_size;
/* /*
extern const u8 icon_gfx_png[]; extern const u8 icon_gfx_png[];
extern const u32 icon_gfx_png_size; extern const u32 icon_gfx_png_size;
extern const u8 icon_pls_png[]; extern const u8 icon_pls_png[];
extern const u32 icon_pls_png_size; extern const u32 icon_pls_png_size;
extern const u8 icon_sfx_png[]; extern const u8 icon_sfx_png[];
extern const u32 icon_sfx_png_size; extern const u32 icon_sfx_png_size;
extern const u8 icon_txt_png[]; extern const u8 icon_txt_png[];
extern const u32 icon_txt_png_size; extern const u32 icon_txt_png_size;
extern const u8 icon_xml_png[]; extern const u8 icon_xml_png[];
extern const u32 icon_xml_png_size; extern const u32 icon_xml_png_size;
*/ */
extern const u8 bg_browser_selection_png[]; extern const u8 bg_browser_selection_png[];
extern const u32 bg_browser_selection_png_size; extern const u32 bg_browser_selection_png_size;
@ -170,380 +170,380 @@ extern const u32 button_install_png_size;
extern const u8 button_install_over_png[]; extern const u8 button_install_over_png[];
extern const u32 button_install_over_png_size; extern const u32 button_install_over_png_size;
extern const u8 dialogue_box_startgame_png[]; extern const u8 dialogue_box_startgame_png[];
extern const u32 dialogue_box_startgame_png_size; extern const u32 dialogue_box_startgame_png_size;
extern const u8 wdialogue_box_startgame_png[]; extern const u8 wdialogue_box_startgame_png[];
extern const u32 wdialogue_box_startgame_png_size; extern const u32 wdialogue_box_startgame_png_size;
extern const u8 button_dialogue_box_startgame_png[]; extern const u8 button_dialogue_box_startgame_png[];
extern const u32 button_dialogue_box_startgame_size; extern const u32 button_dialogue_box_startgame_size;
extern const u8 button_dialogue_box_png[]; extern const u8 button_dialogue_box_png[];
extern const u32 button_dialogue_box_size; extern const u32 button_dialogue_box_size;
extern const u8 keyboard_textbox_png[]; extern const u8 keyboard_textbox_png[];
extern const u32 keyboard_textbox_png_size; extern const u32 keyboard_textbox_png_size;
extern const u8 keyboard_key_png[]; extern const u8 keyboard_key_png[];
extern const u32 keyboard_key_png_size; extern const u32 keyboard_key_png_size;
extern const u8 keyboard_key_over_png[]; extern const u8 keyboard_key_over_png[];
extern const u32 keyboard_key_over_png_size; extern const u32 keyboard_key_over_png_size;
extern const u8 keyboard_mediumkey_over_png[]; extern const u8 keyboard_mediumkey_over_png[];
extern const u32 keyboard_mediumkey_over_png_size; extern const u32 keyboard_mediumkey_over_png_size;
extern const u8 keyboard_largekey_over_png[]; extern const u8 keyboard_largekey_over_png[];
extern const u32 keyboard_largekey_over_png_size; extern const u32 keyboard_largekey_over_png_size;
extern const u8 keyboard_backspace_over_png[]; extern const u8 keyboard_backspace_over_png[];
extern const u32 keyboard_backspace_over_png_size; extern const u32 keyboard_backspace_over_png_size;
extern const u8 keyboard_clear_over_png[]; extern const u8 keyboard_clear_over_png[];
extern const u32 keyboard_clear_over_png_size; extern const u32 keyboard_clear_over_png_size;
extern const u8 menu_button_png[]; extern const u8 menu_button_png[];
extern const u32 menu_button_size; extern const u32 menu_button_size;
extern const u8 menu_button_over_png[]; extern const u8 menu_button_over_png[];
extern const u32 menu_button_over_size; extern const u32 menu_button_over_size;
extern const u8 settings_button_png[]; extern const u8 settings_button_png[];
extern const u32 settings_button_size; extern const u32 settings_button_size;
extern const u8 settings_button_over_png[]; extern const u8 settings_button_over_png[];
extern const u32 settings_button_over_size; extern const u32 settings_button_over_size;
extern const u8 settings_menu_button_png[]; extern const u8 settings_menu_button_png[];
extern const u32 settings_menu_button_size; extern const u32 settings_menu_button_size;
extern const u8 wiimote_poweroff_png[]; extern const u8 wiimote_poweroff_png[];
extern const u32 wiimote_poweroff_png_size; extern const u32 wiimote_poweroff_png_size;
extern const u8 dialogue_box_png[]; extern const u8 dialogue_box_png[];
extern const u32 dialogue_box_png_size; extern const u32 dialogue_box_png_size;
extern const u8 theme_box_png[]; extern const u8 theme_box_png[];
extern const u32 theme_box_png_size; extern const u32 theme_box_png_size;
extern const u8 wiimote_poweroff_over_png[]; extern const u8 wiimote_poweroff_over_png[];
extern const u32 wiimote_poweroff_over_png_size; extern const u32 wiimote_poweroff_over_png_size;
extern const u8 bg_options_png[]; extern const u8 bg_options_png[];
extern const u32 bg_options_png_size; extern const u32 bg_options_png_size;
extern const u8 bg_options_entry_png[]; extern const u8 bg_options_entry_png[];
extern const u32 bg_options_entry_png_size; extern const u32 bg_options_entry_png_size;
extern const u8 scrollbar_png[]; extern const u8 scrollbar_png[];
extern const u32 scrollbar_png_size; extern const u32 scrollbar_png_size;
extern const u8 scrollbar_arrowup_png[]; extern const u8 scrollbar_arrowup_png[];
extern const u32 scrollbar_arrowup_png_size; extern const u32 scrollbar_arrowup_png_size;
extern const u8 scrollbar_arrowup_over_png[]; extern const u8 scrollbar_arrowup_over_png[];
extern const u32 scrollbar_arrowup_over_png_size; extern const u32 scrollbar_arrowup_over_png_size;
extern const u8 scrollbar_arrowdown_png[]; extern const u8 scrollbar_arrowdown_png[];
extern const u32 scrollbar_arrowdown_png_size; extern const u32 scrollbar_arrowdown_png_size;
extern const u8 scrollbar_arrowdown_over_png[]; extern const u8 scrollbar_arrowdown_over_png[];
extern const u32 scrollbar_arrowdown_over_png_size; extern const u32 scrollbar_arrowdown_over_png_size;
extern const u8 scrollbar_box_png[]; extern const u8 scrollbar_box_png[];
extern const u32 scrollbar_box_png_size; extern const u32 scrollbar_box_png_size;
extern const u8 scrollbar_box_over_png[]; extern const u8 scrollbar_box_over_png[];
extern const u32 scrollbar_box_over_png_size; extern const u32 scrollbar_box_over_png_size;
extern const u8 progressbar_png[]; extern const u8 progressbar_png[];
extern const u32 progressbar_png_size; extern const u32 progressbar_png_size;
extern const u8 progressbar_empty_png[]; extern const u8 progressbar_empty_png[];
extern const u32 progressbar_empty_png_size; extern const u32 progressbar_empty_png_size;
extern const u8 progressbar_outline_png[]; extern const u8 progressbar_outline_png[];
extern const u32 progressbar_outline_png_size; extern const u32 progressbar_outline_png_size;
extern const u8 player1_point_png[]; extern const u8 player1_point_png[];
extern const u32 player1_point_png_size; extern const u32 player1_point_png_size;
extern const u8 player2_point_png[]; extern const u8 player2_point_png[];
extern const u32 player2_point_png_size; extern const u32 player2_point_png_size;
extern const u8 player3_point_png[]; extern const u8 player3_point_png[];
extern const u32 player3_point_png_size; extern const u32 player3_point_png_size;
extern const u8 player4_point_png[]; extern const u8 player4_point_png[];
extern const u32 player4_point_png_size; extern const u32 player4_point_png_size;
extern const u8 rplayer1_point_png[]; extern const u8 rplayer1_point_png[];
extern const u32 rplayer1_point_png_size; extern const u32 rplayer1_point_png_size;
extern const u8 rplayer2_point_png[]; extern const u8 rplayer2_point_png[];
extern const u32 rplayer2_point_png_size; extern const u32 rplayer2_point_png_size;
extern const u8 rplayer3_point_png[]; extern const u8 rplayer3_point_png[];
extern const u32 rplayer3_point_png_size; extern const u32 rplayer3_point_png_size;
extern const u8 rplayer4_point_png[]; extern const u8 rplayer4_point_png[];
extern const u32 rplayer4_point_png_size; extern const u32 rplayer4_point_png_size;
extern const u8 battery_png[]; extern const u8 battery_png[];
extern const u32 battery_png_size; extern const u32 battery_png_size;
extern const u8 battery_bar_png[]; extern const u8 battery_bar_png[];
extern const u32 battery_bar_png_size; extern const u32 battery_bar_png_size;
extern const u8 battery_white_png[]; extern const u8 battery_white_png[];
extern const u32 battery_white_png_size; extern const u32 battery_white_png_size;
extern const u8 battery_bar_white_png[]; extern const u8 battery_bar_white_png[];
extern const u32 battery_bar_white_png_size; extern const u32 battery_bar_white_png_size;
extern const u8 battery_red_png[]; extern const u8 battery_red_png[];
extern const u32 battery_red_png_size; extern const u32 battery_red_png_size;
extern const u8 battery_bar_red_png[]; extern const u8 battery_bar_red_png[];
extern const u32 battery_bar_red_png_size; extern const u32 battery_bar_red_png_size;
extern const u8 arrow_next_png[]; extern const u8 arrow_next_png[];
extern const u32 arrow_next_png_size; extern const u32 arrow_next_png_size;
extern const u8 arrow_previous_png[]; extern const u8 arrow_previous_png[];
extern const u32 arrow_previous_png_size; extern const u32 arrow_previous_png_size;
extern const u8 mp3_pause_png[]; extern const u8 mp3_pause_png[];
extern const u32 mp3_pause_png_size; extern const u32 mp3_pause_png_size;
extern const u8 exit_top_png[]; extern const u8 exit_top_png[];
extern const u32 exit_top_png_size; extern const u32 exit_top_png_size;
extern const u8 exit_top_over_png[]; extern const u8 exit_top_over_png[];
extern const u32 exit_top_over_png_size; extern const u32 exit_top_over_png_size;
extern const u8 exit_bottom_png[]; extern const u8 exit_bottom_png[];
extern const u32 exit_bottom_png_size; extern const u32 exit_bottom_png_size;
extern const u8 exit_bottom_over_png[]; extern const u8 exit_bottom_over_png[];
extern const u32 exit_bottom_over_png_size; extern const u32 exit_bottom_over_png_size;
extern const u8 exit_button_png[]; extern const u8 exit_button_png[];
extern const u32 exit_button_png_size; extern const u32 exit_button_png_size;
extern const u8 mp3_stop_png[]; extern const u8 mp3_stop_png[];
extern const u32 mp3_stop_png_size; extern const u32 mp3_stop_png_size;
extern const u8 favorite_png[]; extern const u8 favorite_png[];
extern const u32 favorite_png_size; extern const u32 favorite_png_size;
extern const u8 not_favorite_png[]; extern const u8 not_favorite_png[];
extern const u32 not_favorite_png_size; extern const u32 not_favorite_png_size;
extern const u8 favIcon_png[]; extern const u8 favIcon_png[];
extern const u32 favIcon_png_size; extern const u32 favIcon_png_size;
extern const u8 searchIcon_png[]; extern const u8 searchIcon_png[];
extern const u32 searchIcon_png_size; extern const u32 searchIcon_png_size;
extern const u8 abcIcon_png[]; extern const u8 abcIcon_png[];
extern const u32 abcIcon_png_size; extern const u32 abcIcon_png_size;
extern const u8 rankIcon_png[]; extern const u8 rankIcon_png[];
extern const u32 rankIcon_png_size; extern const u32 rankIcon_png_size;
extern const u8 playCountIcon_png[]; extern const u8 playCountIcon_png[];
extern const u32 playCountIcon_png_size; extern const u32 playCountIcon_png_size;
extern const u8 arrangeList_png[]; extern const u8 arrangeList_png[];
extern const u32 arrangeList_png_size; extern const u32 arrangeList_png_size;
extern const u8 arrangeGrid_png[]; extern const u8 arrangeGrid_png[];
extern const u32 arrangeGrid_png_size; extern const u32 arrangeGrid_png_size;
extern const u8 arrangeCarousel_png[]; extern const u8 arrangeCarousel_png[];
extern const u32 arrangeCarousel_png_size; extern const u32 arrangeCarousel_png_size;
extern const u8 settings_title_png[]; extern const u8 settings_title_png[];
extern const u32 settings_title_png_size; extern const u32 settings_title_png_size;
extern const u8 settings_title_over_png[]; extern const u8 settings_title_over_png[];
extern const u32 settings_title_over_png_size; extern const u32 settings_title_over_png_size;
extern const u8 pageindicator_png[]; extern const u8 pageindicator_png[];
extern const u32 pageindicator_png_size; extern const u32 pageindicator_png_size;
extern const u8 Wiimote1_png[]; extern const u8 Wiimote1_png[];
extern const u32 Wiimote1_png_size; extern const u32 Wiimote1_png_size;
extern const u8 Wiimote2_png[]; extern const u8 Wiimote2_png[];
extern const u32 Wiimote2_png_size; extern const u32 Wiimote2_png_size;
extern const u8 Wiimote4_png[]; extern const u8 Wiimote4_png[];
extern const u32 Wiimote4_png_size; extern const u32 Wiimote4_png_size;
extern const u8 wifi1_png[]; extern const u8 wifi1_png[];
extern const u32 wifi1_png_size; extern const u32 wifi1_png_size;
extern const u8 wifi2_png[]; extern const u8 wifi2_png[];
extern const u32 wifi2png_size; extern const u32 wifi2png_size;
extern const u8 wifi3_png[]; extern const u8 wifi3_png[];
extern const u32 wifi3_png_size; extern const u32 wifi3_png_size;
extern const u8 wifi4_png[]; extern const u8 wifi4_png[];
extern const u32 wifi4_png_size; extern const u32 wifi4_png_size;
//extern const u8 wifi6_png[]; //extern const u8 wifi6_png[];
//extern const u32 wifi6_png_size; //extern const u32 wifi6_png_size;
extern const u8 wifi8_png[]; extern const u8 wifi8_png[];
extern const u32 wifi8_png_size; extern const u32 wifi8_png_size;
extern const u8 wifi12_png[]; extern const u8 wifi12_png[];
extern const u32 wifi12_png_size; extern const u32 wifi12_png_size;
extern const u8 wifi16_png[]; extern const u8 wifi16_png[];
extern const u32 wifi16_png_size; extern const u32 wifi16_png_size;
extern const u8 wifi32_png[]; extern const u8 wifi32_png[];
extern const u32 wifi32_png_size; extern const u32 wifi32_png_size;
extern const u8 norating_png[]; extern const u8 norating_png[];
extern const u32 norating_png_size; extern const u32 norating_png_size;
extern const u8 guitar_png[]; extern const u8 guitar_png[];
extern const u32 guitar_png_size; extern const u32 guitar_png_size;
extern const u8 guitarR_png[]; extern const u8 guitarR_png[];
extern const u32 guitarR_png_size; extern const u32 guitarR_png_size;
extern const u8 microphone_png[]; extern const u8 microphone_png[];
extern const u32 microphone_png_size; extern const u32 microphone_png_size;
extern const u8 microphoneR_png[]; extern const u8 microphoneR_png[];
extern const u32 microphoneR_png_size; extern const u32 microphoneR_png_size;
extern const u8 gcncontroller_png[]; extern const u8 gcncontroller_png[];
extern const u32 gcncontroller_png_size; extern const u32 gcncontroller_png_size;
extern const u8 gcncontrollerR_png[]; extern const u8 gcncontrollerR_png[];
extern const u32 gcncontrollerR_png_size; extern const u32 gcncontrollerR_png_size;
extern const u8 classiccontroller_png[]; extern const u8 classiccontroller_png[];
extern const u32 classiccontroller_png_size; extern const u32 classiccontroller_png_size;
extern const u8 classiccontrollerR_png[]; extern const u8 classiccontrollerR_png[];
extern const u32 classiccontrollerR_png_size; extern const u32 classiccontrollerR_png_size;
extern const u8 nunchuk_png[]; extern const u8 nunchuk_png[];
extern const u32 nunchuk_png_size; extern const u32 nunchuk_png_size;
extern const u8 nunchukR_png[]; extern const u8 nunchukR_png[];
extern const u32 nunchukR_png_size; extern const u32 nunchukR_png_size;
extern const u8 dancepadR_png[]; extern const u8 dancepadR_png[];
extern const u32 dancepadR_size; extern const u32 dancepadR_size;
extern const u8 dancepad_png[]; extern const u8 dancepad_png[];
extern const u32 dancepad_png_size; extern const u32 dancepad_png_size;
extern const u8 balanceboard_png[]; extern const u8 balanceboard_png[];
extern const u32 balanceboard_png_size; extern const u32 balanceboard_png_size;
extern const u8 balanceboardR_png[]; extern const u8 balanceboardR_png[];
extern const u32 balanceboardR_png_size; extern const u32 balanceboardR_png_size;
extern const u8 drums_png[]; extern const u8 drums_png[];
extern const u32 drums_png_size; extern const u32 drums_png_size;
extern const u8 drumsR_png[]; extern const u8 drumsR_png[];
extern const u32 drumsR_png_size; extern const u32 drumsR_png_size;
extern const u8 motionplus_png[]; extern const u8 motionplus_png[];
extern const u32 motionplus_png_size; extern const u32 motionplus_png_size;
extern const u8 motionplusR_png[]; extern const u8 motionplusR_png[];
extern const u32 motionplusR_png_size; extern const u32 motionplusR_png_size;
extern const u8 wheel_png[]; extern const u8 wheel_png[];
extern const u32 wheel_png_size; extern const u32 wheel_png_size;
extern const u8 wheelR_png[]; extern const u8 wheelR_png[];
extern const u32 wheelR_png_size; extern const u32 wheelR_png_size;
extern const u8 zapper_png[]; extern const u8 zapper_png[];
extern const u32 zapper_png_size; extern const u32 zapper_png_size;
extern const u8 zapperR_png[]; extern const u8 zapperR_png[];
extern const u32 zapperR_png_size; extern const u32 zapperR_png_size;
extern const u8 wiispeak_png[]; extern const u8 wiispeak_png[];
extern const u32 wiispeak_png_size; extern const u32 wiispeak_png_size;
extern const u8 wiispeakR_png[]; extern const u8 wiispeakR_png[];
extern const u32 wiispeakR_png_size; extern const u32 wiispeakR_png_size;
extern const u8 nintendods_png[]; extern const u8 nintendods_png[];
extern const u32 nintendods_png_size; extern const u32 nintendods_png_size;
extern const u8 nintendodsR_png[]; extern const u8 nintendodsR_png[];
extern const u32 nintendodsR_png_size; extern const u32 nintendodsR_png_size;
/* /*
extern const u8 vitalitysensor_png[]; extern const u8 vitalitysensor_png[];
extern const u32 vitalitysensor_png_size; extern const u32 vitalitysensor_png_size;
extern const u8 vitalitysensor_png[]; extern const u8 vitalitysensor_png[];
extern const u32 vitalitysensorR_png_size; extern const u32 vitalitysensorR_png_size;
*/ */
extern const u8 esrb_ec_png[]; extern const u8 esrb_ec_png[];
extern const u32 esrb_ec_png_size; extern const u32 esrb_ec_png_size;
extern const u8 esrb_e_png[]; extern const u8 esrb_e_png[];
extern const u32 esrb_e_png_size; extern const u32 esrb_e_png_size;
extern const u8 esrb_eten_png[]; extern const u8 esrb_eten_png[];
extern const u32 esrb_eten_png_size; extern const u32 esrb_eten_png_size;
extern const u8 esrb_t_png[]; extern const u8 esrb_t_png[];
extern const u32 esrb_t_png_size; extern const u32 esrb_t_png_size;
extern const u8 esrb_m_png[]; extern const u8 esrb_m_png[];
extern const u32 esrb_m_png_size; extern const u32 esrb_m_png_size;
extern const u8 esrb_ao_png[]; extern const u8 esrb_ao_png[];
extern const u32 esrb_ao_png_size; extern const u32 esrb_ao_png_size;
extern const u8 cero_a_png[]; extern const u8 cero_a_png[];
extern const u32 cero_a_png_size; extern const u32 cero_a_png_size;
extern const u8 cero_b_png[]; extern const u8 cero_b_png[];
extern const u32 cero_b_png_size; extern const u32 cero_b_png_size;
extern const u8 cero_c_png[]; extern const u8 cero_c_png[];
extern const u32 cero_c_png_size; extern const u32 cero_c_png_size;
extern const u8 cero_d_png[]; extern const u8 cero_d_png[];
extern const u32 cero_d_png_size; extern const u32 cero_d_png_size;
extern const u8 cero_z_png[]; extern const u8 cero_z_png[];
extern const u32 cero_z_png_size; extern const u32 cero_z_png_size;
extern const u8 pegi_3_png[]; extern const u8 pegi_3_png[];
extern const u32 pegi_3_png_size; extern const u32 pegi_3_png_size;
extern const u8 pegi_7_png[]; extern const u8 pegi_7_png[];
extern const u32 pegi_7_png_size; extern const u32 pegi_7_png_size;
extern const u8 pegi_12_png[]; extern const u8 pegi_12_png[];
extern const u32 pegi_12_png_size; extern const u32 pegi_12_png_size;
extern const u8 pegi_16_png[]; extern const u8 pegi_16_png[];
extern const u32 pegi_16_png_size; extern const u32 pegi_16_png_size;
extern const u8 pegi_18_png[]; extern const u8 pegi_18_png[];
extern const u32 pegi_18_png_size; extern const u32 pegi_18_png_size;
extern const u8 usbport_png[]; extern const u8 usbport_png[];
extern const u32 usbport_png_size; extern const u32 usbport_png_size;
extern const u8 dvd_png[]; extern const u8 dvd_png[];
extern const u32 dvd_png_size; extern const u32 dvd_png_size;
extern const u8 new_png[]; extern const u8 new_png[];
extern const u32 new_png_size; extern const u32 new_png_size;
extern const u8 lock_png[]; extern const u8 lock_png[];
extern const u32 lock_png_size; extern const u32 lock_png_size;
extern const u8 unlock_png[]; extern const u8 unlock_png[];
extern const u32 unlock_png_size; extern const u32 unlock_png_size;
#endif #endif

View File

@ -12,67 +12,67 @@ bool textVideoInit = false;
//using the gprintf from crediar because it is smaller than mine //using the gprintf from crediar because it is smaller than mine
void gprintf( const char *str, ... ) void gprintf( const char *str, ... )
{ {
if (!(geckoinit))return; if ( !( geckoinit ) )return;
char astr[4096]; char astr[4096];
va_list ap; va_list ap;
va_start(ap,str); va_start( ap, str );
vsprintf( astr, str, ap ); vsprintf( astr, str, ap );
va_end(ap); va_end( ap );
usb_sendbuffer( 1, astr, strlen(astr) ); usb_sendbuffer( 1, astr, strlen( astr ) );
//usb_sendbuffer_safe( 1, astr, strlen(astr) ); //usb_sendbuffer_safe( 1, astr, strlen(astr) );
} }
bool InitGecko() bool InitGecko()
{ {
u32 geckoattached = usb_isgeckoalive(EXI_CHANNEL_1); u32 geckoattached = usb_isgeckoalive( EXI_CHANNEL_1 );
if (geckoattached) if ( geckoattached )
{ {
usb_flush(EXI_CHANNEL_1); usb_flush( EXI_CHANNEL_1 );
CON_EnableGecko( 1, true ); CON_EnableGecko( 1, true );
return true; return true;
} }
else return false; else return false;
} }
char ascii(char s) char ascii( char s )
{ {
if(s < 0x20) if ( s < 0x20 )
return '.'; return '.';
if(s > 0x7E) if ( s > 0x7E )
return '.'; return '.';
return s; return s;
} }
void hexdump(void *d, int len) void hexdump( void *d, int len )
{ {
u8 *data; u8 *data;
int i, off; int i, off;
data = (u8*)d; data = ( u8* )d;
gprintf("\n 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF"); gprintf( "\n 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF" );
gprintf("\n==== =============================================== ================\n"); gprintf( "\n==== =============================================== ================\n" );
for (off=0; off<len; off += 16) for ( off = 0; off < len; off += 16 )
{ {
gprintf("%04x ",off); gprintf( "%04x ", off );
for(i=0; i<16; i++) for ( i = 0; i < 16; i++ )
if((i+off)>=len) if ( ( i + off ) >= len )
gprintf(" "); gprintf( " " );
else else
gprintf("%02x ",data[off+i]); gprintf( "%02x ", data[off+i] );
gprintf(" "); gprintf( " " );
for(i=0; i<16; i++) for ( i = 0; i < 16; i++ )
if((i+off)>=len) if ( ( i + off ) >= len )
gprintf(" "); gprintf( " " );
else else
gprintf("%c",ascii(data[off+i])); gprintf( "%c", ascii( data[off+i] ) );
gprintf("\n"); gprintf( "\n" );
} }
} }

View File

@ -4,20 +4,21 @@
#define _GECKO_H_ #define _GECKO_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
char ascii(char s); char ascii( char s );
#ifndef NO_DEBUG #ifndef NO_DEBUG
//use this just like printf(); //use this just like printf();
void gprintf(const char *str, ...); void gprintf( const char *str, ... );
bool InitGecko(); bool InitGecko();
void hexdump(void *d, int len); void hexdump( void *d, int len );
#else #else
#define gprintf(...) #define gprintf(...)
#define InitGecko() false #define InitGecko() false
#define hexdump( x, y ) #define hexdump( x, y )
#endif /* NO_DEBUG */ #endif /* NO_DEBUG */

View File

@ -14,62 +14,62 @@
#include "fatmounter.h" #include "fatmounter.h"
#include "sys.h" #include "sys.h"
extern const u8 app_booter_dol[]; extern const u8 app_booter_dol[];
extern const u32 app_booter_dol_size; extern const u32 app_booter_dol_size;
static u8 *homebrewbuffer = (u8 *) 0x92000000; static u8 *homebrewbuffer = ( u8 * ) 0x92000000;
static int homebrewsize = 0; static int homebrewsize = 0;
static std::vector<std::string> Arguments; static std::vector<std::string> Arguments;
void AddBootArgument(const char * argv) void AddBootArgument( const char * argv )
{ {
std::string arg(argv); std::string arg( argv );
Arguments.push_back(arg); Arguments.push_back( arg );
} }
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len) int CopyHomebrewMemory( u8 *temp, u32 pos, u32 len )
{ {
homebrewsize += len; homebrewsize += len;
memcpy((homebrewbuffer)+pos, temp, len); memcpy( ( homebrewbuffer ) + pos, temp, len );
return 1; return 1;
} }
void FreeHomebrewBuffer() void FreeHomebrewBuffer()
{ {
homebrewbuffer = (u8 *)0x92000000; homebrewbuffer = ( u8 * )0x92000000;
homebrewsize = 0; homebrewsize = 0;
} }
static int SetupARGV(struct __argv * args) static int SetupARGV( struct __argv * args )
{ {
if(!args) if ( !args )
return -1; return -1;
bzero(args, sizeof(struct __argv)); bzero( args, sizeof( struct __argv ) );
args->argvMagic = ARGV_MAGIC; args->argvMagic = ARGV_MAGIC;
u32 stringlength = 1; u32 stringlength = 1;
/** Append Arguments **/ /** Append Arguments **/
for(u32 i = 0; i < Arguments.size(); i++) for ( u32 i = 0; i < Arguments.size(); i++ )
{ {
stringlength += Arguments[i].size()+1; stringlength += Arguments[i].size() + 1;
} }
args->length = stringlength; args->length = stringlength;
args->commandLine = (char*) malloc(args->length); args->commandLine = ( char* ) malloc( args->length );
if (!args->commandLine) if ( !args->commandLine )
return -1; return -1;
u32 argc = 0; u32 argc = 0;
u32 position = 0; u32 position = 0;
/** Append Arguments **/ /** Append Arguments **/
for(u32 i = 0; i < Arguments.size(); i++) for ( u32 i = 0; i < Arguments.size(); i++ )
{ {
strcpy(&args->commandLine[position], Arguments[i].c_str()); strcpy( &args->commandLine[position], Arguments[i].c_str() );
position += Arguments[i].size()+1; position += Arguments[i].size() + 1;
argc++; argc++;
} }
@ -86,7 +86,7 @@ static int SetupARGV(struct __argv * args)
int BootHomebrew() int BootHomebrew()
{ {
if(homebrewsize <= 0) if ( homebrewsize <= 0 )
Sys_BackToLoader(); Sys_BackToLoader();
SDCard_deInit(); SDCard_deInit();
@ -94,43 +94,43 @@ int BootHomebrew()
USBStorage2_Deinit(); USBStorage2_Deinit();
struct __argv args; struct __argv args;
SetupARGV(&args); SetupARGV( &args );
u32 cpu_isr; u32 cpu_isr;
entrypoint entry = (entrypoint) load_dol(app_booter_dol, &args); entrypoint entry = ( entrypoint ) load_dol( app_booter_dol, &args );
if (!entry) if ( !entry )
Sys_BackToLoader(); Sys_BackToLoader();
VIDEO_SetBlack(true); VIDEO_SetBlack( true );
VIDEO_Flush(); VIDEO_Flush();
VIDEO_WaitVSync(); VIDEO_WaitVSync();
SYS_ResetSystem(SYS_SHUTDOWN, 0, 0); SYS_ResetSystem( SYS_SHUTDOWN, 0, 0 );
_CPU_ISR_Disable (cpu_isr); _CPU_ISR_Disable ( cpu_isr );
__exception_closeall(); __exception_closeall();
entry(); entry();
_CPU_ISR_Restore (cpu_isr); _CPU_ISR_Restore ( cpu_isr );
return 0; return 0;
} }
int BootHomebrew(const char * filepath) int BootHomebrew( const char * filepath )
{ {
FILE * file = fopen(filepath, "rb"); FILE * file = fopen( filepath, "rb" );
if(!file) if ( !file )
Sys_BackToLoader(); Sys_BackToLoader();
fseek(file, 0, SEEK_END); fseek( file, 0, SEEK_END );
int size = ftell(file); int size = ftell( file );
rewind(file); rewind( file );
homebrewsize = fread(homebrewbuffer, 1, size, file); homebrewsize = fread( homebrewbuffer, 1, size, file );
fclose(file); fclose( file );
AddBootArgument(filepath); AddBootArgument( filepath );
return BootHomebrew(); return BootHomebrew();
} }
@ -155,11 +155,11 @@ int BootHomebrew(const char * filepath)
void *innetbuffer = NULL; void *innetbuffer = NULL;
static u8 *homebrewbuffer =( u8 * )0x92000000; static u8 *homebrewbuffer = ( u8 * )0x92000000;
u32 homebrewsize = 0; u32 homebrewsize = 0;
static std::vector<std::string> Arguments; static std::vector<std::string> Arguments;
extern const u8 app_booter_dol[]; extern const u8 app_booter_dol[];
int AllocHomebrewMemory( u32 filesize ) int AllocHomebrewMemory( u32 filesize )
{ {
@ -167,7 +167,7 @@ int AllocHomebrewMemory( u32 filesize )
innetbuffer = malloc( filesize ); innetbuffer = malloc( filesize );
if ( !innetbuffer ) if ( !innetbuffer )
return -1; return -1;
homebrewsize = filesize; homebrewsize = filesize;
return 1; return 1;
@ -182,7 +182,7 @@ void AddBootArgument( const char * argv )
int CopyHomebrewMemory( u8 *temp, u32 pos, u32 len ) int CopyHomebrewMemory( u8 *temp, u32 pos, u32 len )
{ {
homebrewsize += len; homebrewsize += len;
memcpy(( homebrewbuffer ) + pos, temp, len ); memcpy( ( homebrewbuffer ) + pos, temp, len );
return 1; return 1;
} }
@ -194,8 +194,8 @@ void FreeHomebrewBuffer()
if ( innetbuffer ) if ( innetbuffer )
{ {
free( innetbuffer ); free( innetbuffer );
innetbuffer = NULL; innetbuffer = NULL;
} }
Arguments.clear(); Arguments.clear();
@ -204,7 +204,7 @@ void FreeHomebrewBuffer()
static int SetupARGV( struct __argv * args ) static int SetupARGV( struct __argv * args )
{ {
if ( !args ) if ( !args )
return -1; return -1;
bzero( args, sizeof( struct __argv ) ); bzero( args, sizeof( struct __argv ) );
args->argvMagic = ARGV_MAGIC; args->argvMagic = ARGV_MAGIC;
@ -214,14 +214,14 @@ static int SetupARGV( struct __argv * args )
/** Append Arguments **/ /** Append Arguments **/
for ( u32 i = 0; i < Arguments.size(); i++ ) for ( u32 i = 0; i < Arguments.size(); i++ )
{ {
stringlength += Arguments[i].size() + 1; stringlength += Arguments[i].size() + 1;
} }
args->length = stringlength; args->length = stringlength;
args->commandLine = ( char* ) malloc( args->length ); args->commandLine = ( char* ) malloc( args->length );
if ( !args->commandLine ) if ( !args->commandLine )
return -1; return -1;
u32 argc = 0; u32 argc = 0;
u32 position = 0; u32 position = 0;
@ -229,9 +229,9 @@ static int SetupARGV( struct __argv * args )
/** Append Arguments **/ /** Append Arguments **/
for ( u32 i = 0; i < Arguments.size(); i++ ) for ( u32 i = 0; i < Arguments.size(); i++ )
{ {
strcpy( &args->commandLine[position], Arguments[i].c_str() ); strcpy( &args->commandLine[position], Arguments[i].c_str() );
position += Arguments[i].size() + 1; position += Arguments[i].size() + 1;
argc++; argc++;
} }
args->argc = argc; args->argc = argc;
@ -248,19 +248,19 @@ static int SetupARGV( struct __argv * args )
static int RunAppbooter() static int RunAppbooter()
{ {
if ( homebrewsize == 0 ) if ( homebrewsize == 0 )
return -1; return -1;
struct __argv args; struct __argv args;
SetupARGV( &args ); SetupARGV( &args );
u32 cpu_isr; u32 cpu_isr;
entrypoint entry = ( entrypoint ) load_dol(( void* ) app_booter_dol, &args ); entrypoint entry = ( entrypoint ) load_dol( ( void* ) app_booter_dol, &args );
if ( !entry ) if ( !entry )
{ {
FreeHomebrewBuffer(); FreeHomebrewBuffer();
return -1; return -1;
} }
u64 currentStub = getStubDest(); u64 currentStub = getStubDest();
@ -268,13 +268,13 @@ static int RunAppbooter()
if ( Set_Stub_Split( 0x00010001, "UNEO" ) < 0 ) if ( Set_Stub_Split( 0x00010001, "UNEO" ) < 0 )
{ {
if ( Set_Stub_Split( 0x00010001, "ULNR" ) < 0 ) if ( Set_Stub_Split( 0x00010001, "ULNR" ) < 0 )
{ {
if ( !currentStub ) if ( !currentStub )
currentStub = 0x100000002ULL; currentStub = 0x100000002ULL;
Set_Stub( currentStub ); Set_Stub( currentStub );
} }
} }
SDCard_deInit(); SDCard_deInit();
@ -301,7 +301,7 @@ int BootHomebrew( char * filepath )
FILE *file = fopen( filepath, "rb" ); FILE *file = fopen( filepath, "rb" );
if ( !file ) if ( !file )
Sys_BackToLoader(); Sys_BackToLoader();
fseek( file, 0, SEEK_END ); fseek( file, 0, SEEK_END );
filesize = ftell( file ); filesize = ftell( file );
@ -311,21 +311,21 @@ int BootHomebrew( char * filepath )
if ( fread( buffer, 1, filesize, file ) != filesize ) if ( fread( buffer, 1, filesize, file ) != filesize )
{ {
fclose( file ); fclose( file );
free( buffer ); free( buffer );
SDCard_deInit(); SDCard_deInit();
USBDevice_deInit(); USBDevice_deInit();
Sys_BackToLoader(); Sys_BackToLoader();
} }
fclose( file ); fclose( file );
CopyHomebrewMemory(( u8* ) buffer, 0, filesize ); CopyHomebrewMemory( ( u8* ) buffer, 0, filesize );
if ( buffer ) if ( buffer )
{ {
free( buffer ); free( buffer );
buffer = NULL; buffer = NULL;
} }
AddBootArgument( filepath ); AddBootArgument( filepath );
@ -338,13 +338,13 @@ int BootHomebrewFromMem()
if ( !innetbuffer ) if ( !innetbuffer )
{ {
gprintf( "!innetbuffer\n" ); gprintf( "!innetbuffer\n" );
SDCard_deInit(); SDCard_deInit();
USBDevice_deInit(); USBDevice_deInit();
Sys_BackToLoader(); Sys_BackToLoader();
} }
CopyHomebrewMemory(( u8* ) innetbuffer, 0, homebrewsize ); CopyHomebrewMemory( ( u8* ) innetbuffer, 0, homebrewsize );
free( innetbuffer ); free( innetbuffer );
return RunAppbooter(); return RunAppbooter();

View File

@ -3,11 +3,11 @@
//int BootHomebrew(); //int BootHomebrew();
int BootHomebrewFromMem(); int BootHomebrewFromMem();
int BootHomebrew( char * filepath); int BootHomebrew( char * filepath );
int CopyHomebrewMemory(u8 *temp, u32 pos, u32 len); int CopyHomebrewMemory( u8 *temp, u32 pos, u32 len );
void AddBootArgument(const char * arg); void AddBootArgument( const char * arg );
void FreeHomebrewBuffer(); void FreeHomebrewBuffer();
int LoadHomebrew(const char * filepath); int LoadHomebrew( const char * filepath );
int AllocHomebrewMemory( u32 filesize ); int AllocHomebrewMemory( u32 filesize );
extern void *innetbuffer; extern void *innetbuffer;
extern u32 homebrewsize; extern u32 homebrewsize;

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
#ifndef _HOMEBREWBROWSE_H_ #ifndef _HOMEBREWBROWSE_H_
#define _HOMEBREWBROWSE_H_ #define _HOMEBREWBROWSE_H_
int roundup(float number); int roundup( float number );
int MenuHomebrewBrowse(); int MenuHomebrewBrowse();
#endif #endif

View File

@ -9,108 +9,128 @@
#include "HomebrewFiles.h" #include "HomebrewFiles.h"
HomebrewFiles::HomebrewFiles(const char * path) { HomebrewFiles::HomebrewFiles( const char * path )
{
filecount = 0; filecount = 0;
FileInfo = (FileInfos *) malloc(sizeof(FileInfos)); FileInfo = ( FileInfos * ) malloc( sizeof( FileInfos ) );
if (!FileInfo) { if ( !FileInfo )
{
return; return;
} }
memset(&FileInfo[filecount], 0, sizeof(FileInfos)); memset( &FileInfo[filecount], 0, sizeof( FileInfos ) );
this->LoadPath(path); this->LoadPath( path );
this->SortList(); this->SortList();
} }
HomebrewFiles::~HomebrewFiles() { HomebrewFiles::~HomebrewFiles()
if (FileInfo) { {
free(FileInfo); if ( FileInfo )
{
free( FileInfo );
FileInfo = NULL; FileInfo = NULL;
} }
} }
bool HomebrewFiles::LoadPath(const char * folderpath) { bool HomebrewFiles::LoadPath( const char * folderpath )
{
struct stat st; struct stat st;
DIR_ITER *dir = NULL; DIR_ITER *dir = NULL;
char filename[1024]; char filename[1024];
dir = diropen(folderpath); dir = diropen( folderpath );
if (dir == NULL) { if ( dir == NULL )
{
return false; return false;
} }
while (dirnext(dir,filename,&st) == 0) { while ( dirnext( dir, filename, &st ) == 0 )
if ((st.st_mode & S_IFDIR) != 0) { {
if (strcmp(filename,".") != 0 && strcmp(filename,"..") != 0) { if ( ( st.st_mode & S_IFDIR ) != 0 )
{
if ( strcmp( filename, "." ) != 0 && strcmp( filename, ".." ) != 0 )
{
char currentname[200]; char currentname[200];
snprintf(currentname, sizeof(currentname), "%s%s/", folderpath, filename); snprintf( currentname, sizeof( currentname ), "%s%s/", folderpath, filename );
this->LoadPath(currentname); this->LoadPath( currentname );
} }
} else { }
else
{
char temp[5]; char temp[5];
for (int i = 0; i < 5; i++) { for ( int i = 0; i < 5; i++ )
temp[i] = filename[strlen(filename)-4+i]; {
temp[i] = filename[strlen( filename )-4+i];
} }
if ((strncasecmp(temp, ".dol", 4) == 0 || strncasecmp(temp, ".elf", 4) == 0) if ( ( strncasecmp( temp, ".dol", 4 ) == 0 || strncasecmp( temp, ".elf", 4 ) == 0 )
&& filecount < MAXHOMEBREWS && filename[0]!='.') { && filecount < MAXHOMEBREWS && filename[0] != '.' )
{
FileInfo = (FileInfos *) realloc(FileInfo, (filecount+1)*sizeof(FileInfos)); FileInfo = ( FileInfos * ) realloc( FileInfo, ( filecount + 1 ) * sizeof( FileInfos ) );
if (!FileInfo) { if ( !FileInfo )
free(FileInfo); {
free( FileInfo );
FileInfo = NULL; FileInfo = NULL;
filecount = 0; filecount = 0;
dirclose(dir); dirclose( dir );
return false; return false;
} }
memset(&(FileInfo[filecount]), 0, sizeof(FileInfo)); memset( &( FileInfo[filecount] ), 0, sizeof( FileInfo ) );
strlcpy(FileInfo[filecount].FilePath, folderpath, sizeof(FileInfo[filecount].FilePath)); strlcpy( FileInfo[filecount].FilePath, folderpath, sizeof( FileInfo[filecount].FilePath ) );
strlcpy(FileInfo[filecount].FileName, filename, sizeof(FileInfo[filecount].FileName)); strlcpy( FileInfo[filecount].FileName, filename, sizeof( FileInfo[filecount].FileName ) );
FileInfo[filecount].FileSize = st.st_size; FileInfo[filecount].FileSize = st.st_size;
filecount++; filecount++;
} }
} }
} }
dirclose(dir); dirclose( dir );
return true; return true;
} }
char * HomebrewFiles::GetFilename(int ind) { char * HomebrewFiles::GetFilename( int ind )
if (ind > filecount) {
if ( ind > filecount )
return NULL; return NULL;
else else
return FileInfo[ind].FileName; return FileInfo[ind].FileName;
} }
char * HomebrewFiles::GetFilepath(int ind) { char * HomebrewFiles::GetFilepath( int ind )
if (ind > filecount) {
if ( ind > filecount )
return NULL; return NULL;
else else
return FileInfo[ind].FilePath; return FileInfo[ind].FilePath;
} }
unsigned int HomebrewFiles::GetFilesize(int ind) { unsigned int HomebrewFiles::GetFilesize( int ind )
if (ind > filecount || !filecount || !FileInfo) {
if ( ind > filecount || !filecount || !FileInfo )
return NULL; return NULL;
else else
return FileInfo[ind].FileSize; return FileInfo[ind].FileSize;
} }
int HomebrewFiles::GetFilecount() { int HomebrewFiles::GetFilecount()
{
return filecount; return filecount;
} }
static int ListCompare(const void *a, const void *b) { static int ListCompare( const void *a, const void *b )
FileInfos *ab = (FileInfos*) a; {
FileInfos *bb = (FileInfos*) b; FileInfos *ab = ( FileInfos* ) a;
FileInfos *bb = ( FileInfos* ) b;
return stricmp((char *) ab->FilePath, (char *) bb->FilePath); return stricmp( ( char * ) ab->FilePath, ( char * ) bb->FilePath );
} }
void HomebrewFiles::SortList() { void HomebrewFiles::SortList()
qsort(FileInfo, filecount, sizeof(FileInfos), ListCompare); {
qsort( FileInfo, filecount, sizeof( FileInfos ), ListCompare );
} }

View File

@ -7,38 +7,40 @@
#define MAXHOMEBREWS 500 #define MAXHOMEBREWS 500
typedef struct { typedef struct
{
char FileName[100]; char FileName[100];
char FilePath[150]; char FilePath[150];
unsigned int FileSize; unsigned int FileSize;
} FileInfos; } FileInfos;
class HomebrewFiles { class HomebrewFiles
public: {
//!Constructor public:
//!\param path Path where to check for homebrew files //!Constructor
HomebrewFiles(const char * path); //!\param path Path where to check for homebrew files
//!Destructor HomebrewFiles( const char * path );
~HomebrewFiles(); //!Destructor
//! Load the dol/elf list of a path ~HomebrewFiles();
//!\param path Path where to check for homebrew files //! Load the dol/elf list of a path
bool LoadPath(const char * path); //!\param path Path where to check for homebrew files
//! Get the a filename of the list bool LoadPath( const char * path );
//!\param list index //! Get the a filename of the list
char * GetFilename(int index); //!\param list index
//! Get the a filepath of the list char * GetFilename( int index );
//!\param list index //! Get the a filepath of the list
char * GetFilepath(int index); //!\param list index
//! Get the a filesize of the list char * GetFilepath( int index );
//!\param list index //! Get the a filesize of the list
unsigned int GetFilesize(int index); //!\param list index
//! Get the filecount of the whole list unsigned int GetFilesize( int index );
int GetFilecount(); //! Get the filecount of the whole list
//! Sort list by filepath int GetFilecount();
void SortList(); //! Sort list by filepath
protected: void SortList();
int filecount; protected:
FileInfos *FileInfo; int filecount;
FileInfos *FileInfo;
}; };
#endif #endif

View File

@ -11,58 +11,58 @@
#define ENTRIE_SIZE 8192 #define ENTRIE_SIZE 8192
int HomebrewXML::LoadHomebrewXMLData(const char* filename) int HomebrewXML::LoadHomebrewXMLData( const char* filename )
{ {
mxml_node_t *nodedataHB = NULL; mxml_node_t *nodedataHB = NULL;
mxml_node_t *nodetreeHB = NULL; mxml_node_t *nodetreeHB = NULL;
/* Load XML file */ /* Load XML file */
FILE *filexml; FILE *filexml;
filexml = fopen(filename, "rb"); filexml = fopen( filename, "rb" );
if (!filexml) if ( !filexml )
return -1; return -1;
nodetreeHB = mxmlLoadFile(NULL, filexml, MXML_OPAQUE_CALLBACK); nodetreeHB = mxmlLoadFile( NULL, filexml, MXML_OPAQUE_CALLBACK );
fclose(filexml); fclose( filexml );
if (nodetreeHB == NULL) if ( nodetreeHB == NULL )
return -2; return -2;
nodedataHB = mxmlFindElement(nodetreeHB, nodetreeHB, "app", NULL, NULL, MXML_DESCEND); nodedataHB = mxmlFindElement( nodetreeHB, nodetreeHB, "app", NULL, NULL, MXML_DESCEND );
if (nodedataHB == NULL) if ( nodedataHB == NULL )
return -5; return -5;
char * Entrie = new char[ENTRIE_SIZE]; char * Entrie = new char[ENTRIE_SIZE];
GetTextFromNode(nodedataHB, nodedataHB, (char*) "name", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE); GetTextFromNode( nodedataHB, nodedataHB, ( char* ) "name", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE );
Name = Entrie; Name = Entrie;
GetTextFromNode(nodedataHB, nodedataHB, (char*) "coder", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE); GetTextFromNode( nodedataHB, nodedataHB, ( char* ) "coder", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE );
Coder = Entrie; Coder = Entrie;
GetTextFromNode(nodedataHB, nodedataHB, (char*) "version", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE); GetTextFromNode( nodedataHB, nodedataHB, ( char* ) "version", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE );
Version = Entrie; Version = Entrie;
GetTextFromNode(nodedataHB, nodedataHB, (char*) "short_description", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE); GetTextFromNode( nodedataHB, nodedataHB, ( char* ) "short_description", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE );
ShortDescription = Entrie; ShortDescription = Entrie;
GetTextFromNode(nodedataHB, nodedataHB, (char*) "long_description", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE); GetTextFromNode( nodedataHB, nodedataHB, ( char* ) "long_description", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE );
LongDescription = Entrie; LongDescription = Entrie;
GetTextFromNode(nodedataHB, nodedataHB, (char*) "release_date", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE); GetTextFromNode( nodedataHB, nodedataHB, ( char* ) "release_date", NULL, NULL, MXML_DESCEND, Entrie, ENTRIE_SIZE );
int len = (strlen(Entrie)-6); //length of the date string without the 200000 at the end int len = ( strlen( Entrie ) - 6 ); //length of the date string without the 200000 at the end
if (len == 8) if ( len == 8 )
snprintf(Entrie, ENTRIE_SIZE, "%c%c/%c%c/%c%c%c%c", Entrie[4],Entrie[5],Entrie[6],Entrie[7],Entrie[0],Entrie[1],Entrie[2],Entrie[3]); snprintf( Entrie, ENTRIE_SIZE, "%c%c/%c%c/%c%c%c%c", Entrie[4], Entrie[5], Entrie[6], Entrie[7], Entrie[0], Entrie[1], Entrie[2], Entrie[3] );
else if (len == 6) else if ( len == 6 )
snprintf(Entrie, ENTRIE_SIZE, "%c%c/%c%c%c%c", Entrie[4],Entrie[5],Entrie[0],Entrie[1],Entrie[2],Entrie[3]); snprintf( Entrie, ENTRIE_SIZE, "%c%c/%c%c%c%c", Entrie[4], Entrie[5], Entrie[0], Entrie[1], Entrie[2], Entrie[3] );
else else
snprintf(Entrie, ENTRIE_SIZE, "%s", Entrie); snprintf( Entrie, ENTRIE_SIZE, "%s", Entrie );
Releasedate = Entrie; Releasedate = Entrie;
free(nodedataHB); free( nodedataHB );
free(nodetreeHB); free( nodetreeHB );
delete [] Entrie; delete [] Entrie;

View File

@ -16,7 +16,7 @@ class HomebrewXML
//!Destructor //!Destructor
~HomebrewXML() { }; ~HomebrewXML() { };
//!\param filename Filepath of the XML file //!\param filename Filepath of the XML file
int LoadHomebrewXMLData(const char* filename); int LoadHomebrewXMLData( const char* filename );
//! Get name //! Get name
const char * GetName() { return Name.c_str(); }; const char * GetName() { return Name.c_str(); };
//! Get coder //! Get coder
@ -30,7 +30,7 @@ class HomebrewXML
//! Get longdescription //! Get longdescription
const char * GetLongDescription() { return LongDescription.c_str(); }; const char * GetLongDescription() { return LongDescription.c_str(); };
//! Set Name //! Set Name
void SetName(char * newName) { Name = newName; }; void SetName( char * newName ) { Name = newName; };
protected: protected:
std::string Name; std::string Name;
std::string Coder; std::string Coder;

View File

@ -8,7 +8,8 @@
#include "dolloader.h" #include "dolloader.h"
typedef struct _dolheader { typedef struct _dolheader
{
u32 text_pos[7]; u32 text_pos[7];
u32 data_pos[11]; u32 data_pos[11];
u32 text_start[7]; u32 text_start[7];
@ -20,31 +21,36 @@ typedef struct _dolheader {
u32 entry_point; u32 entry_point;
} dolheader; } dolheader;
u32 load_dol(const void *dolstart, struct __argv *argv) { u32 load_dol( const void *dolstart, struct __argv *argv )
{
u32 i; u32 i;
dolheader *dolfile; dolheader *dolfile;
if (dolstart) { if ( dolstart )
dolfile = (dolheader *) dolstart; {
for (i = 0; i < 7; i++) { dolfile = ( dolheader * ) dolstart;
if ((!dolfile->text_size[i]) || (dolfile->text_start[i] < 0x100)) continue; for ( i = 0; i < 7; i++ )
ICInvalidateRange ((void *) dolfile->text_start[i],dolfile->text_size[i]); {
memcpy((void *) dolfile->text_start[i],dolstart+dolfile->text_pos[i],dolfile->text_size[i]); if ( ( !dolfile->text_size[i] ) || ( dolfile->text_start[i] < 0x100 ) ) continue;
ICInvalidateRange ( ( void * ) dolfile->text_start[i], dolfile->text_size[i] );
memcpy( ( void * ) dolfile->text_start[i], dolstart + dolfile->text_pos[i], dolfile->text_size[i] );
} }
for (i = 0; i < 11; i++) { for ( i = 0; i < 11; i++ )
if ((!dolfile->data_size[i]) || (dolfile->data_start[i] < 0x100)) continue; {
memcpy((void *) dolfile->data_start[i],dolstart+dolfile->data_pos[i],dolfile->data_size[i]); if ( ( !dolfile->data_size[i] ) || ( dolfile->data_start[i] < 0x100 ) ) continue;
DCFlushRangeNoSync ((void *) dolfile->data_start[i],dolfile->data_size[i]); memcpy( ( void * ) dolfile->data_start[i], dolstart + dolfile->data_pos[i], dolfile->data_size[i] );
DCFlushRangeNoSync ( ( void * ) dolfile->data_start[i], dolfile->data_size[i] );
} }
memset ((void *) dolfile->bss_start, 0, dolfile->bss_size); memset ( ( void * ) dolfile->bss_start, 0, dolfile->bss_size );
DCFlushRange((void *) dolfile->bss_start, dolfile->bss_size); DCFlushRange( ( void * ) dolfile->bss_start, dolfile->bss_size );
if (argv && argv->argvMagic == ARGV_MAGIC) { if ( argv && argv->argvMagic == ARGV_MAGIC )
void *new_argv = (void *)(dolfile->entry_point + 8); {
memcpy(new_argv, argv, sizeof(*argv)); void *new_argv = ( void * )( dolfile->entry_point + 8 );
DCFlushRange(new_argv, sizeof(*argv)); memcpy( new_argv, argv, sizeof( *argv ) );
DCFlushRange( new_argv, sizeof( *argv ) );
} }
return dolfile->entry_point; return dolfile->entry_point;

View File

@ -2,13 +2,14 @@
#define _DOLLOADER_H_ #define _DOLLOADER_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
extern void __exception_closeall(); extern void __exception_closeall();
typedef void (*entrypoint) (void); typedef void ( *entrypoint ) ( void );
u32 load_dol(const void *dolstart, struct __argv *argv); u32 load_dol( const void *dolstart, struct __argv *argv );
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -20,9 +20,9 @@
#include "input.h" #include "input.h"
#include "libwiigui/gui.h" #include "libwiigui/gui.h"
int rumbleRequest[4] = {0,0,0,0}; int rumbleRequest[4] = {0, 0, 0, 0};
GuiTrigger userInput[4]; GuiTrigger userInput[4];
static int rumbleCount[4] = {0,0,0,0}; static int rumbleCount[4] = {0, 0, 0, 0};
/**************************************************************************** /****************************************************************************
* UpdatePads * UpdatePads
@ -34,22 +34,22 @@ void UpdatePads()
WPAD_ScanPads(); WPAD_ScanPads();
PAD_ScanPads(); PAD_ScanPads();
for (int i=3; i >= 0; i--) for ( int i = 3; i >= 0; i-- )
{ {
memcpy(&userInput[i].wpad, WPAD_Data(i), sizeof(WPADData)); memcpy( &userInput[i].wpad, WPAD_Data( i ), sizeof( WPADData ) );
userInput[i].chan = i; userInput[i].chan = i;
userInput[i].pad.btns_d = PAD_ButtonsDown(i); userInput[i].pad.btns_d = PAD_ButtonsDown( i );
userInput[i].pad.btns_u = PAD_ButtonsUp(i); userInput[i].pad.btns_u = PAD_ButtonsUp( i );
userInput[i].pad.btns_h = PAD_ButtonsHeld(i); userInput[i].pad.btns_h = PAD_ButtonsHeld( i );
userInput[i].pad.stickX = PAD_StickX(i); userInput[i].pad.stickX = PAD_StickX( i );
userInput[i].pad.stickY = PAD_StickY(i); userInput[i].pad.stickY = PAD_StickY( i );
userInput[i].pad.substickX = PAD_SubStickX(i); userInput[i].pad.substickX = PAD_SubStickX( i );
userInput[i].pad.substickY = PAD_SubStickY(i); userInput[i].pad.substickY = PAD_SubStickY( i );
userInput[i].pad.triggerL = PAD_TriggerL(i); userInput[i].pad.triggerL = PAD_TriggerL( i );
userInput[i].pad.triggerR = PAD_TriggerR(i); userInput[i].pad.triggerR = PAD_TriggerR( i );
if(Settings.rumble == RumbleOn) if ( Settings.rumble == RumbleOn )
DoRumble(i); DoRumble( i );
} }
} }
@ -60,26 +60,28 @@ void UpdatePads()
***************************************************************************/ ***************************************************************************/
void SetupPads() void SetupPads()
{ {
PAD_Init(); PAD_Init();
WPAD_Init(); WPAD_Init();
// read wiimote accelerometer and IR data // read wiimote accelerometer and IR data
WPAD_SetDataFormat(WPAD_CHAN_ALL,WPAD_FMT_BTNS_ACC_IR); WPAD_SetDataFormat( WPAD_CHAN_ALL, WPAD_FMT_BTNS_ACC_IR );
WPAD_SetVRes(WPAD_CHAN_ALL, screenwidth, screenheight); WPAD_SetVRes( WPAD_CHAN_ALL, screenwidth, screenheight );
for(int i=0; i < 4; i++) for ( int i = 0; i < 4; i++ )
{ {
userInput[i].chan = i; userInput[i].chan = i;
} }
} }
/**************************************************************************** /****************************************************************************
* ShutoffRumble * ShutoffRumble
***************************************************************************/ ***************************************************************************/
void ShutoffRumble() { void ShutoffRumble()
for (int i=0;i<4;i++) { {
WPAD_Rumble(i, 0); for ( int i = 0; i < 4; i++ )
{
WPAD_Rumble( i, 0 );
rumbleCount[i] = 0; rumbleCount[i] = 0;
} }
} }
@ -88,17 +90,23 @@ void ShutoffRumble() {
* DoRumble * DoRumble
***************************************************************************/ ***************************************************************************/
void DoRumble(int i) { void DoRumble( int i )
if (rumbleRequest[i] && rumbleCount[i] < 3) { {
WPAD_Rumble(i, 1); // rumble on if ( rumbleRequest[i] && rumbleCount[i] < 3 )
{
WPAD_Rumble( i, 1 ); // rumble on
rumbleCount[i]++; rumbleCount[i]++;
} else if (rumbleRequest[i]) { }
else if ( rumbleRequest[i] )
{
rumbleCount[i] = 20; rumbleCount[i] = 20;
rumbleRequest[i] = 0; rumbleRequest[i] = 0;
} else { }
if (rumbleCount[i]) else
{
if ( rumbleCount[i] )
rumbleCount[i]--; rumbleCount[i]--;
WPAD_Rumble(i, 0); // rumble off WPAD_Rumble( i, 0 ); // rumble off
} }
} }
@ -108,43 +116,49 @@ void DoRumble(int i) {
* Get X/Y value from Wii Joystick (classic, nunchuk) input * Get X/Y value from Wii Joystick (classic, nunchuk) input
***************************************************************************/ ***************************************************************************/
s8 WPAD_Stick(u8 chan, u8 right, int axis) { s8 WPAD_Stick( u8 chan, u8 right, int axis )
{
float mag = 0.0; float mag = 0.0;
float ang = 0.0; float ang = 0.0;
WPADData *data = WPAD_Data(chan); WPADData *data = WPAD_Data( chan );
switch (data->exp.type) { switch ( data->exp.type )
case WPAD_EXP_NUNCHUK: {
case WPAD_EXP_GUITARHERO3: case WPAD_EXP_NUNCHUK:
if (right == 0) { case WPAD_EXP_GUITARHERO3:
mag = data->exp.nunchuk.js.mag; if ( right == 0 )
ang = data->exp.nunchuk.js.ang; {
} mag = data->exp.nunchuk.js.mag;
break; ang = data->exp.nunchuk.js.ang;
}
break;
case WPAD_EXP_CLASSIC: case WPAD_EXP_CLASSIC:
if (right == 0) { if ( right == 0 )
mag = data->exp.classic.ljs.mag; {
ang = data->exp.classic.ljs.ang; mag = data->exp.classic.ljs.mag;
} else { ang = data->exp.classic.ljs.ang;
mag = data->exp.classic.rjs.mag; }
ang = data->exp.classic.rjs.ang; else
} {
break; mag = data->exp.classic.rjs.mag;
ang = data->exp.classic.rjs.ang;
}
break;
default: default:
break; break;
} }
/* calculate x/y value (angle need to be converted into radian) */ /* calculate x/y value (angle need to be converted into radian) */
if (mag > 1.0) mag = 1.0; if ( mag > 1.0 ) mag = 1.0;
else if (mag < -1.0) mag = -1.0; else if ( mag < -1.0 ) mag = -1.0;
double val; double val;
if (axis == 0) // x-axis if ( axis == 0 ) // x-axis
val = mag * sin((PI * ang)/180.0f); val = mag * sin( ( PI * ang ) / 180.0f );
else // y-axis else // y-axis
val = mag * cos((PI * ang)/180.0f); val = mag * cos( ( PI * ang ) / 180.0f );
return (s8)(val * 128.0f); return ( s8 )( val * 128.0f );
} }

View File

@ -12,14 +12,14 @@
#include <gccore.h> #include <gccore.h>
#include <wiiuse/wpad.h> #include <wiiuse/wpad.h>
#define PI 3.14159265f #define PI 3.14159265f
#define PADCAL 50 #define PADCAL 50
extern int rumbleRequest[4]; extern int rumbleRequest[4];
void SetupPads(); void SetupPads();
void UpdatePads(); void UpdatePads();
void ShutoffRumble(); void ShutoffRumble();
void DoRumble(int i); void DoRumble( int i );
#endif #endif

View File

@ -13,46 +13,53 @@
#include "network/networkops.h" #include "network/networkops.h"
#include "network/http.h" #include "network/http.h"
int updateLanguageFiles() { int updateLanguageFiles()
{
char languageFiles[50][MAXLANGUAGEFILES]; char languageFiles[50][MAXLANGUAGEFILES];
//get all the files in the language path //get all the files in the language path
int countfiles = GetAllDirFiles(Settings.languagefiles_path); int countfiles = GetAllDirFiles( Settings.languagefiles_path );
//give up now if we didn't find any //give up now if we didn't find any
if (!countfiles) return -2; if ( !countfiles ) return -2;
//now from the files we got, get only the .lang files //now from the files we got, get only the .lang files
for (int cnt = 0; cnt < countfiles; cnt++) { for ( int cnt = 0; cnt < countfiles; cnt++ )
{
char filename[64]; char filename[64];
strlcpy(filename, GetFileName(cnt),sizeof(filename)); strlcpy( filename, GetFileName( cnt ), sizeof( filename ) );
if (strcasestr(filename,".lang")) { if ( strcasestr( filename, ".lang" ) )
strcpy(languageFiles[cnt],filename); {
strcpy( languageFiles[cnt], filename );
} }
} }
subfoldercreate(Settings.languagefiles_path); subfoldercreate( Settings.languagefiles_path );
//we assume that the network will already be init by another function //we assume that the network will already be init by another function
// ( that has gui eletents in it because this one doesn't) // ( that has gui eletents in it because this one doesn't)
int done = 0,j = 0; int done = 0, j = 0;
if (IsNetworkInit()) { if ( IsNetworkInit() )
{
//build the URL, save path, and download each file and save it //build the URL, save path, and download each file and save it
while (j<countfiles) { while ( j < countfiles )
{
char savepath[150]; char savepath[150];
char codeurl[200]; char codeurl[200];
snprintf(codeurl, sizeof(codeurl), "http://usbloader-gui.googlecode.com/svn/trunk/Languages/%s",languageFiles[j]); snprintf( codeurl, sizeof( codeurl ), "http://usbloader-gui.googlecode.com/svn/trunk/Languages/%s", languageFiles[j] );
snprintf(savepath, sizeof(savepath), "%s%s",Settings.languagefiles_path,languageFiles[j]); snprintf( savepath, sizeof( savepath ), "%s%s", Settings.languagefiles_path, languageFiles[j] );
struct block file = downloadfile(codeurl); struct block file = downloadfile( codeurl );
if (file.data != NULL) { if ( file.data != NULL )
{
FILE * pfile; FILE * pfile;
pfile = fopen(savepath, "wb"); pfile = fopen( savepath, "wb" );
if(pfile != NULL) { if ( pfile != NULL )
fwrite(file.data,1,file.size,pfile); {
fclose(pfile); fwrite( file.data, 1, file.size, pfile );
free(file.data); fclose( pfile );
free( file.data );
done++; done++;
} }
} }

View File

@ -4,12 +4,13 @@
#include <gctypes.h> #include <gctypes.h>
#include "gettext.h" #include "gettext.h"
typedef struct _MSG { typedef struct _MSG
{
u32 id; u32 id;
char* msgstr; char* msgstr;
struct _MSG *next; struct _MSG *next;
} MSG; } MSG;
static MSG *baseMSG=0; static MSG *baseMSG = 0;
#define HASHWORDBITS 32 #define HASHWORDBITS 32
@ -18,18 +19,21 @@ static MSG *baseMSG=0;
[see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1986, 1987 Bell Telephone Laboratories, Inc.] */ 1986, 1987 Bell Telephone Laboratories, Inc.] */
static inline u32 static inline u32
hash_string (const char *str_param) { hash_string ( const char *str_param )
{
u32 hval, g; u32 hval, g;
const char *str = str_param; const char *str = str_param;
/* Compute the hash value for the given string. */ /* Compute the hash value for the given string. */
hval = 0; hval = 0;
while (*str != '\0') { while ( *str != '\0' )
{
hval <<= 4; hval <<= 4;
hval += (u8) *str++; hval += ( u8 ) * str++;
g = hval & ((u32) 0xf << (HASHWORDBITS - 4)); g = hval & ( ( u32 ) 0xf << ( HASHWORDBITS - 4 ) );
if (g != 0) { if ( g != 0 )
hval ^= g >> (HASHWORDBITS - 8); {
hval ^= g >> ( HASHWORDBITS - 8 );
hval ^= g; hval ^= g;
} }
} }
@ -38,88 +42,95 @@ hash_string (const char *str_param) {
/* Expand some escape sequences found in the argument string. */ /* Expand some escape sequences found in the argument string. */
static char * static char *
expand_escape (const char *str) { expand_escape ( const char *str )
{
char *retval, *rp; char *retval, *rp;
const char *cp = str; const char *cp = str;
retval = (char *) malloc (strlen (str)+1); retval = ( char * ) malloc ( strlen ( str ) + 1 );
if (retval==NULL) return NULL; if ( retval == NULL ) return NULL;
rp = retval; rp = retval;
while (cp[0] != '\0' && cp[0] != '\\') while ( cp[0] != '\0' && cp[0] != '\\' )
*rp++ = *cp++; *rp++ = *cp++;
if (cp[0] == '\0') if ( cp[0] == '\0' )
goto terminate; goto terminate;
do { do
{
/* Here cp[0] == '\\'. */ /* Here cp[0] == '\\'. */
switch (*++cp) { switch ( *++cp )
case '\"': /* " */ {
*rp++ = '\"'; case '\"': /* " */
++cp; *rp++ = '\"';
break; ++cp;
case 'a': /* alert */ break;
*rp++ = '\a'; case 'a': /* alert */
++cp; *rp++ = '\a';
break; ++cp;
case 'b': /* backspace */ break;
*rp++ = '\b'; case 'b': /* backspace */
++cp; *rp++ = '\b';
break; ++cp;
case 'f': /* form feed */ break;
*rp++ = '\f'; case 'f': /* form feed */
++cp; *rp++ = '\f';
break; ++cp;
case 'n': /* new line */ break;
*rp++ = '\n'; case 'n': /* new line */
++cp; *rp++ = '\n';
break; ++cp;
case 'r': /* carriage return */ break;
*rp++ = '\r'; case 'r': /* carriage return */
++cp; *rp++ = '\r';
break; ++cp;
case 't': /* horizontal tab */ break;
*rp++ = '\t'; case 't': /* horizontal tab */
++cp; *rp++ = '\t';
break; ++cp;
case 'v': /* vertical tab */ break;
*rp++ = '\v'; case 'v': /* vertical tab */
++cp; *rp++ = '\v';
break; ++cp;
case '\\': break;
*rp = '\\'; case '\\':
++cp; *rp = '\\';
break; ++cp;
case '0': break;
case '1': case '0':
case '2': case '1':
case '3': case '2':
case '4': case '3':
case '5': case '4':
case '6': case '5':
case '7': { case '6':
int ch = *cp++ - '0'; case '7':
{
int ch = *cp++ - '0';
if (*cp >= '0' && *cp <= '7') { if ( *cp >= '0' && *cp <= '7' )
ch *= 8; {
ch += *cp++ - '0';
if (*cp >= '0' && *cp <= '7') {
ch *= 8; ch *= 8;
ch += *cp++ - '0'; ch += *cp++ - '0';
if ( *cp >= '0' && *cp <= '7' )
{
ch *= 8;
ch += *cp++ - '0';
}
} }
*rp = ch;
} }
*rp = ch; break;
} default:
break; *rp = '\\';
default: break;
*rp = '\\';
break;
} }
while (cp[0] != '\0' && cp[0] != '\\') while ( cp[0] != '\0' && cp[0] != '\\' )
*rp++ = *cp++; *rp++ = *cp++;
} while (cp[0] != '\0'); }
while ( cp[0] != '\0' );
/* Terminate string. */ /* Terminate string. */
terminate: terminate:
@ -127,95 +138,112 @@ terminate:
return retval; return retval;
} }
static MSG *findMSG(u32 id) { static MSG *findMSG( u32 id )
{
MSG *msg; MSG *msg;
for (msg=baseMSG; msg; msg=msg->next) { for ( msg = baseMSG; msg; msg = msg->next )
if (msg->id == id) {
if ( msg->id == id )
return msg; return msg;
} }
return NULL; return NULL;
} }
static MSG *setMSG(const char *msgid, const char *msgstr) { static MSG *setMSG( const char *msgid, const char *msgstr )
u32 id = hash_string(msgid); {
MSG *msg = findMSG(id); u32 id = hash_string( msgid );
if (!msg) { MSG *msg = findMSG( id );
msg = (MSG *)malloc(sizeof(MSG)); if ( !msg )
msg->id = id; {
msg = ( MSG * )malloc( sizeof( MSG ) );
msg->id = id;
msg->msgstr = NULL; msg->msgstr = NULL;
msg->next = baseMSG; msg->next = baseMSG;
baseMSG = msg; baseMSG = msg;
} }
if (msg) { if ( msg )
if (msgstr) { {
if (msg->msgstr) free(msg->msgstr); if ( msgstr )
{
if ( msg->msgstr ) free( msg->msgstr );
//msg->msgstr = strdup(msgstr); //msg->msgstr = strdup(msgstr);
msg->msgstr = expand_escape(msgstr); msg->msgstr = expand_escape( msgstr );
} }
return msg; return msg;
} }
return NULL; return NULL;
} }
void gettextCleanUp(void) { void gettextCleanUp( void )
while (baseMSG) { {
MSG *nextMsg =baseMSG->next; while ( baseMSG )
free(baseMSG->msgstr); {
free(baseMSG); MSG *nextMsg = baseMSG->next;
free( baseMSG->msgstr );
free( baseMSG );
baseMSG = nextMsg; baseMSG = nextMsg;
} }
} }
bool gettextLoadLanguage(const char* langFile) { bool gettextLoadLanguage( const char* langFile )
{
FILE *f; FILE *f;
char line[200]; char line[200];
char *lastID=NULL; char *lastID = NULL;
gettextCleanUp(); gettextCleanUp();
f = fopen(langFile, "r"); f = fopen( langFile, "r" );
if (!f) if ( !f )
return false; return false;
while (fgets(line, sizeof(line), f)) { while ( fgets( line, sizeof( line ), f ) )
{
// lines starting with # are comments // lines starting with # are comments
if (line[0] == '#') if ( line[0] == '#' )
continue; continue;
else if (strncmp(line, "msgid \"", 7) == 0) { else if ( strncmp( line, "msgid \"", 7 ) == 0 )
{
char *msgid, *end; char *msgid, *end;
if (lastID) { if ( lastID )
free(lastID); {
lastID=NULL; free( lastID );
lastID = NULL;
} }
msgid = &line[7]; msgid = &line[7];
end = strrchr(msgid, '"'); end = strrchr( msgid, '"' );
if (end && end-msgid>1) { if ( end && end - msgid > 1 )
{
*end = 0; *end = 0;
lastID = strdup(msgid); lastID = strdup( msgid );
} }
} else if (strncmp(line, "msgstr \"", 8) == 0) { }
else if ( strncmp( line, "msgstr \"", 8 ) == 0 )
{
char *msgstr, *end; char *msgstr, *end;
if (lastID == NULL) if ( lastID == NULL )
continue; continue;
msgstr = &line[8]; msgstr = &line[8];
end = strrchr(msgstr, '"'); end = strrchr( msgstr, '"' );
if (end && end-msgstr>1) { if ( end && end - msgstr > 1 )
{
*end = 0; *end = 0;
setMSG(lastID, msgstr); setMSG( lastID, msgstr );
} }
free(lastID); free( lastID );
lastID=NULL; lastID = NULL;
} }
} }
fclose(f); fclose( f );
return true; return true;
} }
const char *gettext(const char *msgid) { const char *gettext( const char *msgid )
MSG *msg = findMSG(hash_string(msgid)); {
if (msg && msg->msgstr) return msg->msgstr; MSG *msg = findMSG( hash_string( msgid ) );
if ( msg && msg->msgstr ) return msg->msgstr;
return msgid; return msgid;
} }

View File

@ -2,17 +2,18 @@
#define _GETTEXT_H_ #define _GETTEXT_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
bool gettextLoadLanguage(const char* langFile); bool gettextLoadLanguage( const char* langFile );
void gettextCleanUp(void); void gettextCleanUp( void );
/* /*
* input msg = a text in ASCII * input msg = a text in ASCII
* output = the translated msg in utf-8 * output = the translated msg in utf-8
*/ */
const char *gettext(const char *msg); const char *gettext( const char *msg );
#define tr(s) gettext(s) #define tr(s) gettext(s)
#define trNOOP(s) (s) #define trNOOP(s) (s)

View File

@ -34,24 +34,28 @@
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
Functions to deal with little endian values stored in uint8_t arrays Functions to deal with little endian values stored in uint8_t arrays
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) { static inline uint16_t u8array_to_u16 ( const uint8_t* item, int offset )
return ( item[offset] | (item[offset + 1] << 8)); {
return ( item[offset] | ( item[offset + 1] << 8 ) );
} }
static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) { static inline uint32_t u8array_to_u32 ( const uint8_t* item, int offset )
return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); {
return ( item[offset] | ( item[offset + 1] << 8 ) | ( item[offset + 2] << 16 ) | ( item[offset + 3] << 24 ) );
} }
static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) { static inline void u16_to_u8array ( uint8_t* item, int offset, uint16_t value )
item[offset] = (uint8_t) value; {
item[offset + 1] = (uint8_t)(value >> 8); item[offset] = ( uint8_t ) value;
item[offset + 1] = ( uint8_t )( value >> 8 );
} }
static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) { static inline void u32_to_u8array ( uint8_t* item, int offset, uint32_t value )
item[offset] = (uint8_t) value; {
item[offset + 1] = (uint8_t)(value >> 8); item[offset] = ( uint8_t ) value;
item[offset + 2] = (uint8_t)(value >> 16); item[offset + 1] = ( uint8_t )( value >> 8 );
item[offset + 3] = (uint8_t)(value >> 24); item[offset + 2] = ( uint8_t )( value >> 16 );
item[offset + 3] = ( uint8_t )( value >> 24 );
} }
#endif // _BIT_OPS_H #endif // _BIT_OPS_H

View File

@ -42,20 +42,22 @@
#define PAGE_SECTORS 64 #define PAGE_SECTORS 64
#define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS) #define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS)
typedef struct { typedef struct
sec_t sector; {
unsigned int count; sec_t sector;
unsigned int last_access; unsigned int count;
bool dirty; unsigned int last_access;
uint8_t* cache; bool dirty;
uint8_t* cache;
} CACHE_ENTRY; } CACHE_ENTRY;
typedef struct { typedef struct
const DISC_INTERFACE* disc; {
sec_t endOfPartition; const DISC_INTERFACE* disc;
unsigned int numberOfPages; sec_t endOfPartition;
unsigned int sectorsPerPage; unsigned int numberOfPages;
CACHE_ENTRY* cacheEntries; unsigned int sectorsPerPage;
CACHE_ENTRY* cacheEntries;
} CACHE; } CACHE;
/* /*
@ -65,9 +67,9 @@ offset is the position to start reading from
size is the amount of data to read size is the amount of data to read
Precondition: offset + size <= BYTES_PER_READ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_readPartialSector ( CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size );
bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes); bool _FAT_cache_readLittleEndianValue ( CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes );
/* /*
Write data to a sector in the cache Write data to a sector in the cache
@ -77,9 +79,9 @@ offset is the position to start writing to
size is the amount of data to write size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_writePartialSector ( CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size );
bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes); bool _FAT_cache_writeLittleEndianValue ( CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes );
/* /*
Write data to a sector in the cache, zeroing the sector first Write data to a sector in the cache, zeroing the sector first
@ -89,42 +91,44 @@ offset is the position to start writing to
size is the amount of data to write size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_eraseWritePartialSector ( CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size );
/* /*
Read several sectors from the cache Read several sectors from the cache
*/ */
bool _FAT_cache_readSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer); bool _FAT_cache_readSectors ( CACHE* cache, sec_t sector, sec_t numSectors, void* buffer );
/* /*
Read a full sector from the cache Read a full sector from the cache
*/ */
static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) { static inline bool _FAT_cache_readSector ( CACHE* cache, void* buffer, sec_t sector )
return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); {
return _FAT_cache_readPartialSector ( cache, buffer, sector, 0, BYTES_PER_READ );
} }
/* /*
Write a full sector to the cache Write a full sector to the cache
*/ */
static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) { static inline bool _FAT_cache_writeSector ( CACHE* cache, const void* buffer, sec_t sector )
return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); {
return _FAT_cache_writePartialSector ( cache, buffer, sector, 0, BYTES_PER_READ );
} }
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer); bool _FAT_cache_writeSectors ( CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer );
/* /*
Write any dirty sectors back to disc and clear out the contents of the cache Write any dirty sectors back to disc and clear out the contents of the cache
*/ */
bool _FAT_cache_flush (CACHE* cache); bool _FAT_cache_flush ( CACHE* cache );
/* /*
Clear out the contents of the cache without writing any dirty sectors first Clear out the contents of the cache without writing any dirty sectors first
*/ */
void _FAT_cache_invalidate (CACHE* cache); void _FAT_cache_invalidate ( CACHE* cache );
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition); CACHE* _FAT_cache_constructor ( unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition );
void _FAT_cache_destructor (CACHE* cache); void _FAT_cache_destructor ( CACHE* cache );
#endif // _CACHE_H #endif // _CACHE_H

File diff suppressed because it is too large Load Diff

View File

@ -36,8 +36,8 @@
#include "partition.h" #include "partition.h"
#define DIR_ENTRY_DATA_SIZE 0x20 #define DIR_ENTRY_DATA_SIZE 0x20
#define MAX_LFN_LENGTH 256 #define MAX_LFN_LENGTH 256
#define MAX_FILENAME_LENGTH 768 // 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars #define MAX_FILENAME_LENGTH 768 // 256 UCS-2 characters encoded into UTF-8 can use up to 768 UTF-8 chars
#define MAX_ALIAS_LENGTH 13 #define MAX_ALIAS_LENGTH 13
#define LFN_ENTRY_LENGTH 13 #define LFN_ENTRY_LENGTH 13
#define ALIAS_ENTRY_LENGTH 11 #define ALIAS_ENTRY_LENGTH 11
@ -49,60 +49,66 @@
#define DIR_SEPARATOR '/' #define DIR_SEPARATOR '/'
// File attributes // File attributes
#define ATTRIB_ARCH 0x20 // Archive #define ATTRIB_ARCH 0x20 // Archive
#define ATTRIB_DIR 0x10 // Directory #define ATTRIB_DIR 0x10 // Directory
#define ATTRIB_LFN 0x0F // Long file name #define ATTRIB_LFN 0x0F // Long file name
#define ATTRIB_VOL 0x08 // Volume #define ATTRIB_VOL 0x08 // Volume
#define ATTRIB_SYS 0x04 // System #define ATTRIB_SYS 0x04 // System
#define ATTRIB_HID 0x02 // Hidden #define ATTRIB_HID 0x02 // Hidden
#define ATTRIB_RO 0x01 // Read only #define ATTRIB_RO 0x01 // Read only
typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE; typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE;
typedef struct { typedef struct
uint32_t cluster; {
sec_t sector; uint32_t cluster;
int32_t offset; sec_t sector;
int32_t offset;
} DIR_ENTRY_POSITION; } DIR_ENTRY_POSITION;
typedef struct { typedef struct
uint8_t entryData[DIR_ENTRY_DATA_SIZE]; {
DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN uint8_t entryData[DIR_ENTRY_DATA_SIZE];
DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry DIR_ENTRY_POSITION dataStart; // Points to the start of the LFN entries of a file, or the alias for no LFN
char filename[MAX_FILENAME_LENGTH]; DIR_ENTRY_POSITION dataEnd; // Always points to the file/directory's alias entry
char filename[MAX_FILENAME_LENGTH];
} DIR_ENTRY; } DIR_ENTRY;
// Directory entry offsets // Directory entry offsets
enum DIR_ENTRY_offset { enum DIR_ENTRY_offset
DIR_ENTRY_name = 0x00, {
DIR_ENTRY_extension = 0x08, DIR_ENTRY_name = 0x00,
DIR_ENTRY_attributes = 0x0B, DIR_ENTRY_extension = 0x08,
DIR_ENTRY_reserved = 0x0C, DIR_ENTRY_attributes = 0x0B,
DIR_ENTRY_cTime_ms = 0x0D, DIR_ENTRY_reserved = 0x0C,
DIR_ENTRY_cTime = 0x0E, DIR_ENTRY_cTime_ms = 0x0D,
DIR_ENTRY_cDate = 0x10, DIR_ENTRY_cTime = 0x0E,
DIR_ENTRY_aDate = 0x12, DIR_ENTRY_cDate = 0x10,
DIR_ENTRY_clusterHigh = 0x14, DIR_ENTRY_aDate = 0x12,
DIR_ENTRY_mTime = 0x16, DIR_ENTRY_clusterHigh = 0x14,
DIR_ENTRY_mDate = 0x18, DIR_ENTRY_mTime = 0x16,
DIR_ENTRY_cluster = 0x1A, DIR_ENTRY_mDate = 0x18,
DIR_ENTRY_fileSize = 0x1C DIR_ENTRY_cluster = 0x1A,
DIR_ENTRY_fileSize = 0x1C
}; };
/* /*
Returns true if the file specified by entry is a directory Returns true if the file specified by entry is a directory
*/ */
static inline bool _FAT_directory_isDirectory (DIR_ENTRY* entry) { static inline bool _FAT_directory_isDirectory ( DIR_ENTRY* entry )
return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR) != 0); {
return ( ( entry->entryData[DIR_ENTRY_attributes] & ATTRIB_DIR ) != 0 );
} }
static inline bool _FAT_directory_isWritable (DIR_ENTRY* entry) { static inline bool _FAT_directory_isWritable ( DIR_ENTRY* entry )
return ((entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO) == 0); {
return ( ( entry->entryData[DIR_ENTRY_attributes] & ATTRIB_RO ) == 0 );
} }
static inline bool _FAT_directory_isDot (DIR_ENTRY* entry) { static inline bool _FAT_directory_isDot ( DIR_ENTRY* entry )
return ((entry->filename[0] == '.') && ((entry->filename[1] == '\0') || {
((entry->filename[1] == '.') && entry->filename[2] == '\0'))); return ( ( entry->filename[0] == '.' ) && ( ( entry->filename[1] == '\0' ) ||
( ( entry->filename[1] == '.' ) && entry->filename[2] == '\0' ) ) );
} }
/* /*
@ -111,7 +117,7 @@ Places result in entry
entry will be destroyed even if no directory entry is found entry will be destroyed even if no directory entry is found
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_getFirstEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); bool _FAT_directory_getFirstEntry ( PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster );
/* /*
Reads the next directory entry after the one already pointed to by entry Reads the next directory entry after the one already pointed to by entry
@ -119,7 +125,7 @@ Places result in entry
entry will be destroyed even if no directory entry is found entry will be destroyed even if no directory entry is found
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_getNextEntry (PARTITION* partition, DIR_ENTRY* entry); bool _FAT_directory_getNextEntry ( PARTITION* partition, DIR_ENTRY* entry );
/* /*
Gets the directory entry corrsponding to the supplied path Gets the directory entry corrsponding to the supplied path
@ -130,20 +136,20 @@ pathEnd specifies the end of the path string, for cutting strings short if neede
after pathEND. after pathEND.
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_entryFromPath (PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd); bool _FAT_directory_entryFromPath ( PARTITION* partition, DIR_ENTRY* entry, const char* path, const char* pathEnd );
/* /*
Changes the current directory to the one specified by path Changes the current directory to the one specified by path
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_chdir (PARTITION* partition, const char* path); bool _FAT_directory_chdir ( PARTITION* partition, const char* path );
/* /*
Removes the directory entry specified by entry Removes the directory entry specified by entry
Assumes that entry is valid Assumes that entry is valid
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_removeEntry (PARTITION* partition, DIR_ENTRY* entry); bool _FAT_directory_removeEntry ( PARTITION* partition, DIR_ENTRY* entry );
/* /*
Add a directory entry to the directory specified by dirCluster Add a directory entry to the directory specified by dirCluster
@ -151,23 +157,23 @@ The fileData, dataStart and dataEnd elements of the DIR_ENTRY struct are
updated with the new directory entry position and alias. updated with the new directory entry position and alias.
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_addEntry (PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster); bool _FAT_directory_addEntry ( PARTITION* partition, DIR_ENTRY* entry, uint32_t dirCluster );
/* /*
Get the start cluster of a file from it's entry data Get the start cluster of a file from it's entry data
*/ */
uint32_t _FAT_directory_entryGetCluster (PARTITION* partition, const uint8_t* entryData); uint32_t _FAT_directory_entryGetCluster ( PARTITION* partition, const uint8_t* entryData );
/* /*
Fill in the file name and entry data of DIR_ENTRY* entry. Fill in the file name and entry data of DIR_ENTRY* entry.
Assumes that the entry's dataStart and dataEnd are correct Assumes that the entry's dataStart and dataEnd are correct
Returns true on success, false on failure Returns true on success, false on failure
*/ */
bool _FAT_directory_entryFromPosition (PARTITION* partition, DIR_ENTRY* entry); bool _FAT_directory_entryFromPosition ( PARTITION* partition, DIR_ENTRY* entry );
/* /*
Fill in a stat struct based on a file entry Fill in a stat struct based on a file entry
*/ */
void _FAT_directory_entryStat (PARTITION* partition, DIR_ENTRY* entry, struct stat *st); void _FAT_directory_entryStat ( PARTITION* partition, DIR_ENTRY* entry, struct stat *st );
#endif // _DIRECTORY_H #endif // _DIRECTORY_H

View File

@ -2,9 +2,9 @@
disc.h disc.h
Interface to the low level disc functions. Used by the higher level Interface to the low level disc functions. Used by the higher level
file system code. file system code.
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
@ -32,12 +32,13 @@
#include "common.h" #include "common.h"
/* /*
A list of all default devices to try at startup, A list of all default devices to try at startup,
terminated by a {NULL,NULL} entry. terminated by a {NULL,NULL} entry.
*/ */
typedef struct { typedef struct
const char* name; {
const DISC_INTERFACE* (*getInterface)(void); const char* name;
const DISC_INTERFACE* ( *getInterface )( void );
} INTERFACE_ID; } INTERFACE_ID;
extern const INTERFACE_ID _FAT_disc_interfaces[]; extern const INTERFACE_ID _FAT_disc_interfaces[];
@ -45,66 +46,74 @@ extern const INTERFACE_ID _FAT_disc_interfaces[];
Check if a disc is inserted Check if a disc is inserted
Return true if a disc is inserted and ready, false otherwise Return true if a disc is inserted and ready, false otherwise
*/ */
static inline bool _FAT_disc_isInserted (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_isInserted ( const DISC_INTERFACE* disc )
return disc->isInserted(); {
return disc->isInserted();
} }
/* /*
Read numSectors sectors from a disc, starting at sector. Read numSectors sectors from a disc, starting at sector.
numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined, numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined,
else it is at least 1 else it is at least 1
sector is 0 or greater sector is 0 or greater
buffer is a pointer to the memory to fill buffer is a pointer to the memory to fill
*/ */
static inline bool _FAT_disc_readSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer) { static inline bool _FAT_disc_readSectors ( const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer )
return disc->readSectors (sector, numSectors, buffer); {
return disc->readSectors ( sector, numSectors, buffer );
} }
/* /*
Write numSectors sectors to a disc, starting at sector. Write numSectors sectors to a disc, starting at sector.
numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined, numSectors is between 1 and LIMIT_SECTORS if LIMIT_SECTORS is defined,
else it is at least 1 else it is at least 1
sector is 0 or greater sector is 0 or greater
buffer is a pointer to the memory to read from buffer is a pointer to the memory to read from
*/ */
static inline bool _FAT_disc_writeSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer) { static inline bool _FAT_disc_writeSectors ( const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer )
return disc->writeSectors (sector, numSectors, buffer); {
return disc->writeSectors ( sector, numSectors, buffer );
} }
/* /*
Reset the card back to a ready state Reset the card back to a ready state
*/ */
static inline bool _FAT_disc_clearStatus (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_clearStatus ( const DISC_INTERFACE* disc )
return disc->clearStatus(); {
return disc->clearStatus();
} }
/* /*
Initialise the disc to a state ready for data reading or writing Initialise the disc to a state ready for data reading or writing
*/ */
static inline bool _FAT_disc_startup (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_startup ( const DISC_INTERFACE* disc )
return disc->startup(); {
return disc->startup();
} }
/* /*
Put the disc in a state ready for power down. Put the disc in a state ready for power down.
Complete any pending writes and disable the disc if necessary Complete any pending writes and disable the disc if necessary
*/ */
static inline bool _FAT_disc_shutdown (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_shutdown ( const DISC_INTERFACE* disc )
return disc->shutdown(); {
return disc->shutdown();
} }
/* /*
Return a 32 bit value unique to each type of interface Return a 32 bit value unique to each type of interface
*/ */
static inline uint32_t _FAT_disc_hostType (const DISC_INTERFACE* disc) { static inline uint32_t _FAT_disc_hostType ( const DISC_INTERFACE* disc )
return disc->ioType; {
return disc->ioType;
} }
/* /*
Return a 32 bit value that specifies the capabilities of the disc Return a 32 bit value that specifies the capabilities of the disc
*/ */
static inline uint32_t _FAT_disc_features (const DISC_INTERFACE* disc) { static inline uint32_t _FAT_disc_features ( const DISC_INTERFACE* disc )
return disc->features; {
return disc->features;
} }
#endif // _DISC_H #endif // _DISC_H

View File

@ -43,25 +43,30 @@ The list is terminated by a NULL/NULL entry.
#include "usbloader/usbstorage2.h" #include "usbloader/usbstorage2.h"
#include <sdcard/gcsd.h> #include <sdcard/gcsd.h>
static const DISC_INTERFACE* get_io_wiisd (void) { static const DISC_INTERFACE* get_io_wiisd ( void )
return &__io_wiisd; {
return &__io_wiisd;
} }
static const DISC_INTERFACE* get_io_usbstorage (void) { static const DISC_INTERFACE* get_io_usbstorage ( void )
return &__io_usbstorage2; {
return &__io_usbstorage2;
} }
static const DISC_INTERFACE* get_io_gcsda (void) { static const DISC_INTERFACE* get_io_gcsda ( void )
return &__io_gcsda; {
return &__io_gcsda;
} }
static const DISC_INTERFACE* get_io_gcsdb (void) { static const DISC_INTERFACE* get_io_gcsdb ( void )
return &__io_gcsdb; {
return &__io_gcsdb;
} }
const INTERFACE_ID _FAT_disc_interfaces[] = { const INTERFACE_ID _FAT_disc_interfaces[] =
{"sd", get_io_wiisd}, {
{"usb", get_io_usbstorage}, {"sd", get_io_wiisd},
{"carda", get_io_gcsda}, {"usb", get_io_usbstorage},
{"cardb", get_io_gcsdb}, {"carda", get_io_gcsda},
{NULL, NULL} {"cardb", get_io_gcsdb},
{NULL, NULL}
}; };

View File

@ -35,9 +35,10 @@
A list of all default devices to try at startup, A list of all default devices to try at startup,
terminated by a {NULL,NULL} entry. terminated by a {NULL,NULL} entry.
*/ */
typedef struct { typedef struct
const char* name; {
const DISC_INTERFACE* (*getInterface)(void); const char* name;
const DISC_INTERFACE* ( *getInterface )( void );
} INTERFACE_ID; } INTERFACE_ID;
extern const INTERFACE_ID _FAT_disc_interfaces[]; extern const INTERFACE_ID _FAT_disc_interfaces[];
@ -45,8 +46,9 @@ extern const INTERFACE_ID _FAT_disc_interfaces[];
Check if a disc is inserted Check if a disc is inserted
Return true if a disc is inserted and ready, false otherwise Return true if a disc is inserted and ready, false otherwise
*/ */
static inline bool _FAT_disc_isInserted (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_isInserted ( const DISC_INTERFACE* disc )
return disc->isInserted(); {
return disc->isInserted();
} }
/* /*
@ -56,8 +58,9 @@ else it is at least 1
sector is 0 or greater sector is 0 or greater
buffer is a pointer to the memory to fill buffer is a pointer to the memory to fill
*/ */
static inline bool _FAT_disc_readSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer) { static inline bool _FAT_disc_readSectors ( const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, void* buffer )
return disc->readSectors (sector, numSectors, buffer); {
return disc->readSectors ( sector, numSectors, buffer );
} }
/* /*
@ -67,44 +70,50 @@ else it is at least 1
sector is 0 or greater sector is 0 or greater
buffer is a pointer to the memory to read from buffer is a pointer to the memory to read from
*/ */
static inline bool _FAT_disc_writeSectors (const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer) { static inline bool _FAT_disc_writeSectors ( const DISC_INTERFACE* disc, sec_t sector, sec_t numSectors, const void* buffer )
return disc->writeSectors (sector, numSectors, buffer); {
return disc->writeSectors ( sector, numSectors, buffer );
} }
/* /*
Reset the card back to a ready state Reset the card back to a ready state
*/ */
static inline bool _FAT_disc_clearStatus (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_clearStatus ( const DISC_INTERFACE* disc )
return disc->clearStatus(); {
return disc->clearStatus();
} }
/* /*
Initialise the disc to a state ready for data reading or writing Initialise the disc to a state ready for data reading or writing
*/ */
static inline bool _FAT_disc_startup (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_startup ( const DISC_INTERFACE* disc )
return disc->startup(); {
return disc->startup();
} }
/* /*
Put the disc in a state ready for power down. Put the disc in a state ready for power down.
Complete any pending writes and disable the disc if necessary Complete any pending writes and disable the disc if necessary
*/ */
static inline bool _FAT_disc_shutdown (const DISC_INTERFACE* disc) { static inline bool _FAT_disc_shutdown ( const DISC_INTERFACE* disc )
return disc->shutdown(); {
return disc->shutdown();
} }
/* /*
Return a 32 bit value unique to each type of interface Return a 32 bit value unique to each type of interface
*/ */
static inline uint32_t _FAT_disc_hostType (const DISC_INTERFACE* disc) { static inline uint32_t _FAT_disc_hostType ( const DISC_INTERFACE* disc )
return disc->ioType; {
return disc->ioType;
} }
/* /*
Return a 32 bit value that specifies the capabilities of the disc Return a 32 bit value that specifies the capabilities of the disc
*/ */
static inline uint32_t _FAT_disc_features (const DISC_INTERFACE* disc) { static inline uint32_t _FAT_disc_features ( const DISC_INTERFACE* disc )
return disc->features; {
return disc->features;
} }
#endif // _DISC_H #endif // _DISC_H

View File

@ -1,6 +1,6 @@
/* /*
fat.h fat.h
Simple functionality for startup, mounting and unmounting of FAT-based devices. Simple functionality for startup, mounting and unmounting of FAT-based devices.
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 Michael "Chishm" Chisholm
@ -31,47 +31,48 @@
#define _LIBFAT_H #define _LIBFAT_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C"
{
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <ogc/disc_io.h> #include <ogc/disc_io.h>
/* /*
Initialise any inserted block-devices. Initialise any inserted block-devices.
Add the fat device driver to the devoptab, making it available for standard file functions. Add the fat device driver to the devoptab, making it available for standard file functions.
cacheSize: The number of pages to allocate for each inserted block-device cacheSize: The number of pages to allocate for each inserted block-device
setAsDefaultDevice: if true, make this the default device driver for file operations setAsDefaultDevice: if true, make this the default device driver for file operations
*/ */
extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice); extern bool fatInit ( uint32_t cacheSize, bool setAsDefaultDevice );
/* /*
Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system. Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system.
*/ */
extern bool fatInitDefault (void); extern bool fatInitDefault ( void );
/* /*
Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". Mount the device pointed to by interface, and set up a devoptab entry for it as "name:".
You can then access the filesystem using "name:/". You can then access the filesystem using "name:/".
This will mount the active partition or the first valid partition on the disc, This will mount the active partition or the first valid partition on the disc,
and will use a cache size optimized for the host system. and will use a cache size optimized for the host system.
*/ */
extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface); extern bool fatMountSimple ( const char* name, const DISC_INTERFACE* interface );
/* /*
Mount the device pointed to by interface, and set up a devoptab entry for it as "name:". Mount the device pointed to by interface, and set up a devoptab entry for it as "name:".
You can then access the filesystem using "name:/". You can then access the filesystem using "name:/".
If startSector = 0, it will mount the active partition of the first valid partition on If startSector = 0, it will mount the active partition of the first valid partition on
the disc. Otherwise it will try to mount the partition starting at startSector. the disc. Otherwise it will try to mount the partition starting at startSector.
cacheSize specifies the number of pages to allocate for the cache. cacheSize specifies the number of pages to allocate for the cache.
This will not startup the disc, so you need to call interface->startup(); first. This will not startup the disc, so you need to call interface->startup(); first.
*/ */
extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage); extern bool fatMount ( const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage );
/* /*
Unmount the partition specified by name. Unmount the partition specified by name.
If there are open files, it will attempt to synchronise them to disc. If there are open files, it will attempt to synchronise them to disc.
*/ */
extern void fatUnmount (const char* name); extern void fatUnmount ( const char* name );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -46,321 +46,356 @@
#define CACHE_FREE UINT_MAX #define CACHE_FREE UINT_MAX
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition) { CACHE* _FAT_cache_constructor ( unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition )
CACHE* cache; {
unsigned int i; CACHE* cache;
CACHE_ENTRY* cacheEntries; unsigned int i;
CACHE_ENTRY* cacheEntries;
if (numberOfPages < 2) { if ( numberOfPages < 2 )
numberOfPages = 2; {
} numberOfPages = 2;
}
if (sectorsPerPage < 8) { if ( sectorsPerPage < 8 )
sectorsPerPage = 8; {
} sectorsPerPage = 8;
}
cache = (CACHE*) _FAT_mem_allocate (sizeof(CACHE)); cache = ( CACHE* ) _FAT_mem_allocate ( sizeof( CACHE ) );
if (cache == NULL) { if ( cache == NULL )
return NULL; {
} return NULL;
}
cache->disc = discInterface; cache->disc = discInterface;
cache->endOfPartition = endOfPartition; cache->endOfPartition = endOfPartition;
cache->numberOfPages = numberOfPages; cache->numberOfPages = numberOfPages;
cache->sectorsPerPage = sectorsPerPage; cache->sectorsPerPage = sectorsPerPage;
cacheEntries = (CACHE_ENTRY*) _FAT_mem_allocate ( sizeof(CACHE_ENTRY) * numberOfPages); cacheEntries = ( CACHE_ENTRY* ) _FAT_mem_allocate ( sizeof( CACHE_ENTRY ) * numberOfPages );
if (cacheEntries == NULL) { if ( cacheEntries == NULL )
_FAT_mem_free (cache); {
return NULL; _FAT_mem_free ( cache );
} return NULL;
}
for (i = 0; i < numberOfPages; i++) { for ( i = 0; i < numberOfPages; i++ )
cacheEntries[i].sector = CACHE_FREE; {
cacheEntries[i].count = 0; cacheEntries[i].sector = CACHE_FREE;
cacheEntries[i].last_access = 0; cacheEntries[i].count = 0;
cacheEntries[i].dirty = false; cacheEntries[i].last_access = 0;
cacheEntries[i].cache = (uint8_t*) _FAT_mem_align ( sectorsPerPage * BYTES_PER_READ ); cacheEntries[i].dirty = false;
} cacheEntries[i].cache = ( uint8_t* ) _FAT_mem_align ( sectorsPerPage * BYTES_PER_READ );
}
cache->cacheEntries = cacheEntries; cache->cacheEntries = cacheEntries;
return cache; return cache;
} }
void _FAT_cache_destructor (CACHE* cache) { void _FAT_cache_destructor ( CACHE* cache )
unsigned int i; {
// Clear out cache before destroying it unsigned int i;
_FAT_cache_flush(cache); // Clear out cache before destroying it
_FAT_cache_flush( cache );
// Free memory in reverse allocation order // Free memory in reverse allocation order
for (i = 0; i < cache->numberOfPages; i++) { for ( i = 0; i < cache->numberOfPages; i++ )
_FAT_mem_free (cache->cacheEntries[i].cache); {
} _FAT_mem_free ( cache->cacheEntries[i].cache );
_FAT_mem_free (cache->cacheEntries); }
_FAT_mem_free (cache); _FAT_mem_free ( cache->cacheEntries );
_FAT_mem_free ( cache );
} }
static u32 accessCounter = 0; static u32 accessCounter = 0;
static u32 accessTime(){ static u32 accessTime()
accessCounter++; {
return accessCounter; accessCounter++;
return accessCounter;
} }
static CACHE_ENTRY* _FAT_cache_getPage(CACHE *cache,sec_t sector) static CACHE_ENTRY* _FAT_cache_getPage( CACHE *cache, sec_t sector )
{ {
unsigned int i; unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries; CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages; unsigned int numberOfPages = cache->numberOfPages;
unsigned int sectorsPerPage = cache->sectorsPerPage; unsigned int sectorsPerPage = cache->sectorsPerPage;
bool foundFree = false; bool foundFree = false;
unsigned int oldUsed = 0; unsigned int oldUsed = 0;
unsigned int oldAccess = UINT_MAX; unsigned int oldAccess = UINT_MAX;
for(i=0;i<numberOfPages;i++) { for ( i = 0; i < numberOfPages; i++ )
if(sector>=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) { {
cacheEntries[i].last_access = accessTime(); if ( sector >= cacheEntries[i].sector && sector < ( cacheEntries[i].sector + cacheEntries[i].count ) )
return &(cacheEntries[i]); {
} cacheEntries[i].last_access = accessTime();
return &( cacheEntries[i] );
}
if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_access<oldAccess)) { if ( foundFree == false && ( cacheEntries[i].sector == CACHE_FREE || cacheEntries[i].last_access < oldAccess ) )
if(cacheEntries[i].sector==CACHE_FREE) foundFree = true; {
oldUsed = i; if ( cacheEntries[i].sector == CACHE_FREE ) foundFree = true;
oldAccess = cacheEntries[i].last_access; oldUsed = i;
} oldAccess = cacheEntries[i].last_access;
} }
}
if(foundFree==false && cacheEntries[oldUsed].dirty==true) { if ( foundFree == false && cacheEntries[oldUsed].dirty == true )
if(!_FAT_disc_writeSectors(cache->disc,cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL; {
cacheEntries[oldUsed].dirty = false; if ( !_FAT_disc_writeSectors( cache->disc, cacheEntries[oldUsed].sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache ) ) return NULL;
} cacheEntries[oldUsed].dirty = false;
}
sector = (sector/sectorsPerPage)*sectorsPerPage; // align base sector to page size sector = ( sector / sectorsPerPage ) * sectorsPerPage; // align base sector to page size
sec_t next_page = sector + sectorsPerPage; sec_t next_page = sector + sectorsPerPage;
if(next_page > cache->endOfPartition) next_page = cache->endOfPartition; if ( next_page > cache->endOfPartition ) next_page = cache->endOfPartition;
if(!_FAT_disc_readSectors(cache->disc,sector,next_page-sector,cacheEntries[oldUsed].cache)) return NULL; if ( !_FAT_disc_readSectors( cache->disc, sector, next_page - sector, cacheEntries[oldUsed].cache ) ) return NULL;
cacheEntries[oldUsed].sector = sector; cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = next_page-sector; cacheEntries[oldUsed].count = next_page - sector;
cacheEntries[oldUsed].last_access = accessTime(); cacheEntries[oldUsed].last_access = accessTime();
return &(cacheEntries[oldUsed]); return &( cacheEntries[oldUsed] );
} }
bool _FAT_cache_readSectors(CACHE *cache,sec_t sector,sec_t numSectors,void *buffer) bool _FAT_cache_readSectors( CACHE *cache, sec_t sector, sec_t numSectors, void *buffer )
{ {
sec_t sec; sec_t sec;
sec_t secs_to_read; sec_t secs_to_read;
CACHE_ENTRY *entry; CACHE_ENTRY *entry;
uint8_t *dest = buffer; uint8_t *dest = buffer;
while(numSectors>0) { while ( numSectors > 0 )
entry = _FAT_cache_getPage(cache,sector); {
if(entry==NULL) return false; entry = _FAT_cache_getPage( cache, sector );
if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
secs_to_read = entry->count - sec; secs_to_read = entry->count - sec;
if(secs_to_read>numSectors) secs_to_read = numSectors; if ( secs_to_read > numSectors ) secs_to_read = numSectors;
memcpy(dest,entry->cache + (sec*BYTES_PER_READ),(secs_to_read*BYTES_PER_READ)); memcpy( dest, entry->cache + ( sec*BYTES_PER_READ ), ( secs_to_read*BYTES_PER_READ ) );
dest += (secs_to_read*BYTES_PER_READ); dest += ( secs_to_read * BYTES_PER_READ );
sector += secs_to_read; sector += secs_to_read;
numSectors -= secs_to_read; numSectors -= secs_to_read;
} }
return true; return true;
} }
/* /*
Reads some data from a cache page, determined by the sector number Reads some data from a cache page, determined by the sector number
*/ */
bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) bool _FAT_cache_readPartialSector ( CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size )
{ {
sec_t sec; sec_t sec;
CACHE_ENTRY *entry; CACHE_ENTRY *entry;
if (offset + size > BYTES_PER_READ) return false; if ( offset + size > BYTES_PER_READ ) return false;
entry = _FAT_cache_getPage(cache,sector); entry = _FAT_cache_getPage( cache, sector );
if(entry==NULL) return false; if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
memcpy(buffer,entry->cache + ((sec*BYTES_PER_READ) + offset),size); memcpy( buffer, entry->cache + ( ( sec*BYTES_PER_READ ) + offset ), size );
return true; return true;
} }
bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) { bool _FAT_cache_readLittleEndianValue ( CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes )
uint8_t buf[4]; {
if (!_FAT_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false; uint8_t buf[4];
if ( !_FAT_cache_readPartialSector( cache, buf, sector, offset, num_bytes ) ) return false;
switch(num_bytes) { switch ( num_bytes )
case 1: *value = buf[0]; break; {
case 2: *value = u8array_to_u16(buf,0); break; case 1: *value = buf[0]; break;
case 4: *value = u8array_to_u32(buf,0); break; case 2: *value = u8array_to_u16( buf, 0 ); break;
default: return false; case 4: *value = u8array_to_u32( buf, 0 ); break;
} default: return false;
return true; }
return true;
} }
/* /*
Writes some data to a cache page, making sure it is loaded into memory first. Writes some data to a cache page, making sure it is loaded into memory first.
*/ */
bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) bool _FAT_cache_writePartialSector ( CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size )
{ {
sec_t sec; sec_t sec;
CACHE_ENTRY *entry; CACHE_ENTRY *entry;
if (offset + size > BYTES_PER_READ) return false; if ( offset + size > BYTES_PER_READ ) return false;
entry = _FAT_cache_getPage(cache,sector); entry = _FAT_cache_getPage( cache, sector );
if(entry==NULL) return false; if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
memcpy(entry->cache + ((sec*BYTES_PER_READ) + offset),buffer,size); memcpy( entry->cache + ( ( sec*BYTES_PER_READ ) + offset ), buffer, size );
entry->dirty = true; entry->dirty = true;
return true; return true;
} }
bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) { bool _FAT_cache_writeLittleEndianValue ( CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size )
uint8_t buf[4] = {0, 0, 0, 0}; {
uint8_t buf[4] = {0, 0, 0, 0};
switch(size) { switch ( size )
case 1: buf[0] = value; break; {
case 2: u16_to_u8array(buf, 0, value); break; case 1: buf[0] = value; break;
case 4: u32_to_u8array(buf, 0, value); break; case 2: u16_to_u8array( buf, 0, value ); break;
default: return false; case 4: u32_to_u8array( buf, 0, value ); break;
} default: return false;
}
return _FAT_cache_writePartialSector(cache, buf, sector, offset, size); return _FAT_cache_writePartialSector( cache, buf, sector, offset, size );
} }
/* /*
Writes some data to a cache page, zeroing out the page first Writes some data to a cache page, zeroing out the page first
*/ */
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) bool _FAT_cache_eraseWritePartialSector ( CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size )
{ {
sec_t sec; sec_t sec;
CACHE_ENTRY *entry; CACHE_ENTRY *entry;
if (offset + size > BYTES_PER_READ) return false; if ( offset + size > BYTES_PER_READ ) return false;
entry = _FAT_cache_getPage(cache,sector); entry = _FAT_cache_getPage( cache, sector );
if(entry==NULL) return false; if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
memset(entry->cache + (sec*BYTES_PER_READ),0,BYTES_PER_READ); memset( entry->cache + ( sec*BYTES_PER_READ ), 0, BYTES_PER_READ );
memcpy(entry->cache + ((sec*BYTES_PER_READ) + offset),buffer,size); memcpy( entry->cache + ( ( sec*BYTES_PER_READ ) + offset ), buffer, size );
entry->dirty = true; entry->dirty = true;
return true; return true;
} }
static CACHE_ENTRY* _FAT_cache_findPage(CACHE *cache, sec_t sector, sec_t count) { static CACHE_ENTRY* _FAT_cache_findPage( CACHE *cache, sec_t sector, sec_t count )
{
unsigned int i; unsigned int i;
CACHE_ENTRY* cacheEntries = cache->cacheEntries; CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages; unsigned int numberOfPages = cache->numberOfPages;
CACHE_ENTRY *entry = NULL; CACHE_ENTRY *entry = NULL;
sec_t lowest = UINT_MAX; sec_t lowest = UINT_MAX;
for(i=0;i<numberOfPages;i++) { for ( i = 0; i < numberOfPages; i++ )
if (cacheEntries[i].sector != CACHE_FREE) { {
bool intersect; if ( cacheEntries[i].sector != CACHE_FREE )
if (sector > cacheEntries[i].sector) { {
intersect = sector - cacheEntries[i].sector < cacheEntries[i].count; bool intersect;
} else { if ( sector > cacheEntries[i].sector )
intersect = cacheEntries[i].sector - sector < count; {
} intersect = sector - cacheEntries[i].sector < cacheEntries[i].count;
}
else
{
intersect = cacheEntries[i].sector - sector < count;
}
if ( intersect && (cacheEntries[i].sector < lowest)) { if ( intersect && ( cacheEntries[i].sector < lowest ) )
lowest = cacheEntries[i].sector; {
entry = &cacheEntries[i]; lowest = cacheEntries[i].sector;
} entry = &cacheEntries[i];
} }
} }
}
return entry; return entry;
} }
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer) bool _FAT_cache_writeSectors ( CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer )
{ {
sec_t sec; sec_t sec;
sec_t secs_to_write; sec_t secs_to_write;
CACHE_ENTRY* entry; CACHE_ENTRY* entry;
const uint8_t *src = buffer; const uint8_t *src = buffer;
while(numSectors>0) while ( numSectors > 0 )
{ {
entry = _FAT_cache_findPage(cache,sector,numSectors); entry = _FAT_cache_findPage( cache, sector, numSectors );
if(entry!=NULL) { if ( entry != NULL )
{
if ( entry->sector > sector) { if ( entry->sector > sector )
{
secs_to_write = entry->sector - sector; secs_to_write = entry->sector - sector;
_FAT_disc_writeSectors(cache->disc,sector,secs_to_write,src); _FAT_disc_writeSectors( cache->disc, sector, secs_to_write, src );
src += (secs_to_write*BYTES_PER_READ); src += ( secs_to_write * BYTES_PER_READ );
sector += secs_to_write; sector += secs_to_write;
numSectors -= secs_to_write; numSectors -= secs_to_write;
} }
sec = sector - entry->sector; sec = sector - entry->sector;
secs_to_write = entry->count - sec; secs_to_write = entry->count - sec;
if(secs_to_write>numSectors) secs_to_write = numSectors; if ( secs_to_write > numSectors ) secs_to_write = numSectors;
memcpy(entry->cache + (sec*BYTES_PER_READ),src,(secs_to_write*BYTES_PER_READ)); memcpy( entry->cache + ( sec*BYTES_PER_READ ), src, ( secs_to_write*BYTES_PER_READ ) );
src += (secs_to_write*BYTES_PER_READ); src += ( secs_to_write * BYTES_PER_READ );
sector += secs_to_write; sector += secs_to_write;
numSectors -= secs_to_write; numSectors -= secs_to_write;
entry->dirty = true; entry->dirty = true;
} else { }
_FAT_disc_writeSectors(cache->disc,sector,numSectors,src); else
numSectors=0; {
} _FAT_disc_writeSectors( cache->disc, sector, numSectors, src );
} numSectors = 0;
return true; }
}
return true;
} }
/* /*
Flushes all dirty pages to disc, clearing the dirty flag. Flushes all dirty pages to disc, clearing the dirty flag.
*/ */
bool _FAT_cache_flush (CACHE* cache) { bool _FAT_cache_flush ( CACHE* cache )
unsigned int i; {
unsigned int i;
for (i = 0; i < cache->numberOfPages; i++) { for ( i = 0; i < cache->numberOfPages; i++ )
if (cache->cacheEntries[i].dirty) { {
if (!_FAT_disc_writeSectors (cache->disc, cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) { if ( cache->cacheEntries[i].dirty )
return false; {
} if ( !_FAT_disc_writeSectors ( cache->disc, cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache ) )
} {
cache->cacheEntries[i].dirty = false; return false;
} }
}
cache->cacheEntries[i].dirty = false;
}
return true; return true;
} }
void _FAT_cache_invalidate (CACHE* cache) { void _FAT_cache_invalidate ( CACHE* cache )
unsigned int i; {
_FAT_cache_flush(cache); unsigned int i;
for (i = 0; i < cache->numberOfPages; i++) { _FAT_cache_flush( cache );
cache->cacheEntries[i].sector = CACHE_FREE; for ( i = 0; i < cache->numberOfPages; i++ )
cache->cacheEntries[i].last_access = 0; {
cache->cacheEntries[i].count = 0; cache->cacheEntries[i].sector = CACHE_FREE;
cache->cacheEntries[i].dirty = false; cache->cacheEntries[i].last_access = 0;
} cache->cacheEntries[i].count = 0;
cache->cacheEntries[i].dirty = false;
}
} }

View File

@ -42,20 +42,22 @@
#define PAGE_SECTORS 64 #define PAGE_SECTORS 64
#define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS) #define CACHE_PAGE_SIZE (BYTES_PER_READ * PAGE_SECTORS)
typedef struct { typedef struct
sec_t sector; {
unsigned int count; sec_t sector;
unsigned int last_access; unsigned int count;
bool dirty; unsigned int last_access;
uint8_t* cache; bool dirty;
uint8_t* cache;
} CACHE_ENTRY; } CACHE_ENTRY;
typedef struct { typedef struct
const DISC_INTERFACE* disc; {
sec_t endOfPartition; const DISC_INTERFACE* disc;
unsigned int numberOfPages; sec_t endOfPartition;
unsigned int sectorsPerPage; unsigned int numberOfPages;
CACHE_ENTRY* cacheEntries; unsigned int sectorsPerPage;
CACHE_ENTRY* cacheEntries;
} CACHE; } CACHE;
/* /*
@ -65,9 +67,9 @@ offset is the position to start reading from
size is the amount of data to read size is the amount of data to read
Precondition: offset + size <= BYTES_PER_READ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_readPartialSector (CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_readPartialSector ( CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size );
bool _FAT_cache_readLittleEndianValue (CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes); bool _FAT_cache_readLittleEndianValue ( CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes );
/* /*
Write data to a sector in the cache Write data to a sector in the cache
@ -77,9 +79,9 @@ offset is the position to start writing to
size is the amount of data to write size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_writePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_writePartialSector ( CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size );
bool _FAT_cache_writeLittleEndianValue (CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes); bool _FAT_cache_writeLittleEndianValue ( CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int num_bytes );
/* /*
Write data to a sector in the cache, zeroing the sector first Write data to a sector in the cache, zeroing the sector first
@ -89,42 +91,44 @@ offset is the position to start writing to
size is the amount of data to write size is the amount of data to write
Precondition: offset + size <= BYTES_PER_READ Precondition: offset + size <= BYTES_PER_READ
*/ */
bool _FAT_cache_eraseWritePartialSector (CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size); bool _FAT_cache_eraseWritePartialSector ( CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size );
/* /*
Read several sectors from the cache Read several sectors from the cache
*/ */
bool _FAT_cache_readSectors (CACHE* cache, sec_t sector, sec_t numSectors, void* buffer); bool _FAT_cache_readSectors ( CACHE* cache, sec_t sector, sec_t numSectors, void* buffer );
/* /*
Read a full sector from the cache Read a full sector from the cache
*/ */
static inline bool _FAT_cache_readSector (CACHE* cache, void* buffer, sec_t sector) { static inline bool _FAT_cache_readSector ( CACHE* cache, void* buffer, sec_t sector )
return _FAT_cache_readPartialSector (cache, buffer, sector, 0, BYTES_PER_READ); {
return _FAT_cache_readPartialSector ( cache, buffer, sector, 0, BYTES_PER_READ );
} }
/* /*
Write a full sector to the cache Write a full sector to the cache
*/ */
static inline bool _FAT_cache_writeSector (CACHE* cache, const void* buffer, sec_t sector) { static inline bool _FAT_cache_writeSector ( CACHE* cache, const void* buffer, sec_t sector )
return _FAT_cache_writePartialSector (cache, buffer, sector, 0, BYTES_PER_READ); {
return _FAT_cache_writePartialSector ( cache, buffer, sector, 0, BYTES_PER_READ );
} }
bool _FAT_cache_writeSectors (CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer); bool _FAT_cache_writeSectors ( CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer );
/* /*
Write any dirty sectors back to disc and clear out the contents of the cache Write any dirty sectors back to disc and clear out the contents of the cache
*/ */
bool _FAT_cache_flush (CACHE* cache); bool _FAT_cache_flush ( CACHE* cache );
/* /*
Clear out the contents of the cache without writing any dirty sectors first Clear out the contents of the cache without writing any dirty sectors first
*/ */
void _FAT_cache_invalidate (CACHE* cache); void _FAT_cache_invalidate ( CACHE* cache );
CACHE* _FAT_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition); CACHE* _FAT_cache_constructor ( unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition );
void _FAT_cache_destructor (CACHE* cache); void _FAT_cache_destructor ( CACHE* cache );
#endif // _CACHE_H #endif // _CACHE_H

File diff suppressed because it is too large Load Diff

View File

@ -39,35 +39,36 @@
#include "common.h" #include "common.h"
#include "directory.h" #include "directory.h"
typedef struct { typedef struct
PARTITION* partition; {
DIR_ENTRY currentEntry; PARTITION* partition;
uint32_t startCluster; DIR_ENTRY currentEntry;
bool inUse; uint32_t startCluster;
bool validEntry; bool inUse;
bool validEntry;
} DIR_STATE_STRUCT; } DIR_STATE_STRUCT;
extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); extern int _FAT_stat_r ( struct _reent *r, const char *path, struct stat *st );
extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); extern int _FAT_link_r ( struct _reent *r, const char *existing, const char *newLink );
extern int _FAT_unlink_r (struct _reent *r, const char *name); extern int _FAT_unlink_r ( struct _reent *r, const char *name );
extern int _FAT_chdir_r (struct _reent *r, const char *name); extern int _FAT_chdir_r ( struct _reent *r, const char *name );
extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); extern int _FAT_rename_r ( struct _reent *r, const char *oldName, const char *newName );
extern int _FAT_mkdir_r (struct _reent *r, const char *path, int mode); extern int _FAT_mkdir_r ( struct _reent *r, const char *path, int mode );
extern int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf); extern int _FAT_statvfs_r ( struct _reent *r, const char *path, struct statvfs *buf );
/* /*
Directory iterator functions Directory iterator functions
*/ */
extern DIR_ITER* _FAT_diropen_r(struct _reent *r, DIR_ITER *dirState, const char *path); extern DIR_ITER* _FAT_diropen_r( struct _reent *r, DIR_ITER *dirState, const char *path );
extern int _FAT_dirreset_r (struct _reent *r, DIR_ITER *dirState); extern int _FAT_dirreset_r ( struct _reent *r, DIR_ITER *dirState );
extern int _FAT_dirnext_r (struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); extern int _FAT_dirnext_r ( struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat );
extern int _FAT_dirclose_r (struct _reent *r, DIR_ITER *dirState); extern int _FAT_dirclose_r ( struct _reent *r, DIR_ITER *dirState );
#endif // _FATDIR_H #endif // _FATDIR_H

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
/* /*
fatfile.h fatfile.h
Functions used by the newlib disc stubs to interface with Functions used by the newlib disc stubs to interface with
this library this library
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
@ -39,67 +39,69 @@
#include "partition.h" #include "partition.h"
#include "directory.h" #include "directory.h"
#define FILE_MAX_SIZE ((uint32_t)0xFFFFFFFF) // 4GiB - 1B #define FILE_MAX_SIZE ((uint32_t)0xFFFFFFFF) // 4GiB - 1B
typedef struct { typedef struct
u32 cluster; {
sec_t sector; u32 cluster;
s32 byte; sec_t sector;
s32 byte;
} FILE_POSITION; } FILE_POSITION;
struct _FILE_STRUCT; struct _FILE_STRUCT;
struct _FILE_STRUCT { struct _FILE_STRUCT
uint32_t filesize; {
uint32_t startCluster; uint32_t filesize;
uint32_t currentPosition; uint32_t startCluster;
FILE_POSITION rwPosition; uint32_t currentPosition;
FILE_POSITION appendPosition; FILE_POSITION rwPosition;
DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN FILE_POSITION appendPosition;
DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry DIR_ENTRY_POSITION dirEntryStart; // Points to the start of the LFN entries of a file, or the alias for no LFN
PARTITION* partition; DIR_ENTRY_POSITION dirEntryEnd; // Always points to the file's alias entry
struct _FILE_STRUCT* prevOpenFile; // The previous entry in a double-linked list of open files PARTITION* partition;
struct _FILE_STRUCT* nextOpenFile; // The next entry in a double-linked list of open files struct _FILE_STRUCT* prevOpenFile; // The previous entry in a double-linked list of open files
bool read; struct _FILE_STRUCT* nextOpenFile; // The next entry in a double-linked list of open files
bool write; bool read;
bool append; bool write;
bool inUse; bool append;
bool modified; bool inUse;
bool modified;
}; };
typedef struct _FILE_STRUCT FILE_STRUCT; typedef struct _FILE_STRUCT FILE_STRUCT;
extern int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode); extern int _FAT_open_r ( struct _reent *r, void *fileStruct, const char *path, int flags, int mode );
extern int _FAT_close_r (struct _reent *r, int fd); extern int _FAT_close_r ( struct _reent *r, int fd );
extern ssize_t _FAT_write_r (struct _reent *r,int fd, const char *ptr, size_t len); extern ssize_t _FAT_write_r ( struct _reent *r, int fd, const char *ptr, size_t len );
extern ssize_t _FAT_read_r (struct _reent *r, int fd, char *ptr, size_t len); extern ssize_t _FAT_read_r ( struct _reent *r, int fd, char *ptr, size_t len );
extern off_t _FAT_seek_r (struct _reent *r, int fd, off_t pos, int dir); extern off_t _FAT_seek_r ( struct _reent *r, int fd, off_t pos, int dir );
extern int _FAT_fstat_r (struct _reent *r, int fd, struct stat *st); extern int _FAT_fstat_r ( struct _reent *r, int fd, struct stat *st );
extern int _FAT_stat_r (struct _reent *r, const char *path, struct stat *st); extern int _FAT_stat_r ( struct _reent *r, const char *path, struct stat *st );
extern int _FAT_link_r (struct _reent *r, const char *existing, const char *newLink); extern int _FAT_link_r ( struct _reent *r, const char *existing, const char *newLink );
extern int _FAT_unlink_r (struct _reent *r, const char *name); extern int _FAT_unlink_r ( struct _reent *r, const char *name );
extern int _FAT_chdir_r (struct _reent *r, const char *name); extern int _FAT_chdir_r ( struct _reent *r, const char *name );
extern int _FAT_rename_r (struct _reent *r, const char *oldName, const char *newName); extern int _FAT_rename_r ( struct _reent *r, const char *oldName, const char *newName );
extern int _FAT_ftruncate_r (struct _reent *r, int fd, off_t len); extern int _FAT_ftruncate_r ( struct _reent *r, int fd, off_t len );
extern int _FAT_fsync_r (struct _reent *r, int fd); extern int _FAT_fsync_r ( struct _reent *r, int fd );
/* /*
Synchronizes the file data to disc. Synchronizes the file data to disc.
Does no locking of its own -- lock the partition before calling. Does no locking of its own -- lock the partition before calling.
Returns 0 on success, an error code on failure. Returns 0 on success, an error code on failure.
*/ */
extern int _FAT_syncToDisc (FILE_STRUCT* file); extern int _FAT_syncToDisc ( FILE_STRUCT* file );
#endif // _FATFILE_H #endif // _FATFILE_H

View File

@ -35,166 +35,179 @@
/* /*
Gets the cluster linked from input cluster Gets the cluster linked from input cluster
*/ */
uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster) uint32_t _FAT_fat_nextCluster( PARTITION* partition, uint32_t cluster )
{ {
uint32_t nextCluster = CLUSTER_FREE; uint32_t nextCluster = CLUSTER_FREE;
sec_t sector; sec_t sector;
int offset; int offset;
if (cluster == CLUSTER_FREE) { if ( cluster == CLUSTER_FREE )
return CLUSTER_FREE; {
} return CLUSTER_FREE;
}
switch (partition->filesysType) switch ( partition->filesysType )
{ {
case FS_UNKNOWN: case FS_UNKNOWN:
return CLUSTER_ERROR; return CLUSTER_ERROR;
break; break;
case FS_FAT12: case FS_FAT12:
{ {
u32 nextCluster_h; u32 nextCluster_h;
sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); sector = partition->fat.fatStart + ( ( ( cluster * 3 ) / 2 ) / BYTES_PER_READ );
offset = ((cluster * 3) / 2) % BYTES_PER_READ; offset = ( ( cluster * 3 ) / 2 ) % BYTES_PER_READ;
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u8)); _FAT_cache_readLittleEndianValue ( partition->cache, &nextCluster, sector, offset, sizeof( u8 ) );
offset++; offset++;
if (offset >= BYTES_PER_READ) { if ( offset >= BYTES_PER_READ )
offset = 0; {
sector++; offset = 0;
} sector++;
nextCluster_h = 0; }
nextCluster_h = 0;
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster_h, sector, offset, sizeof(u8)); _FAT_cache_readLittleEndianValue ( partition->cache, &nextCluster_h, sector, offset, sizeof( u8 ) );
nextCluster |= (nextCluster_h << 8); nextCluster |= ( nextCluster_h << 8 );
if (cluster & 0x01) { if ( cluster & 0x01 )
nextCluster = nextCluster >> 4; {
} else { nextCluster = nextCluster >> 4;
nextCluster &= 0x0FFF; }
} else
{
nextCluster &= 0x0FFF;
}
if (nextCluster >= 0x0FF7) if ( nextCluster >= 0x0FF7 )
{ {
nextCluster = CLUSTER_EOF; nextCluster = CLUSTER_EOF;
} }
break; break;
} }
case FS_FAT16: case FS_FAT16:
sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); sector = partition->fat.fatStart + ( ( cluster << 1 ) / BYTES_PER_READ );
offset = (cluster % (BYTES_PER_READ >> 1)) << 1; offset = ( cluster % ( BYTES_PER_READ >> 1 ) ) << 1;
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u16)); _FAT_cache_readLittleEndianValue ( partition->cache, &nextCluster, sector, offset, sizeof( u16 ) );
if (nextCluster >= 0xFFF7) { if ( nextCluster >= 0xFFF7 )
nextCluster = CLUSTER_EOF; {
} nextCluster = CLUSTER_EOF;
break; }
break;
case FS_FAT32: case FS_FAT32:
sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); sector = partition->fat.fatStart + ( ( cluster << 2 ) / BYTES_PER_READ );
offset = (cluster % (BYTES_PER_READ >> 2)) << 2; offset = ( cluster % ( BYTES_PER_READ >> 2 ) ) << 2;
_FAT_cache_readLittleEndianValue (partition->cache, &nextCluster, sector, offset, sizeof(u32)); _FAT_cache_readLittleEndianValue ( partition->cache, &nextCluster, sector, offset, sizeof( u32 ) );
if (nextCluster >= 0x0FFFFFF7) { if ( nextCluster >= 0x0FFFFFF7 )
nextCluster = CLUSTER_EOF; {
} nextCluster = CLUSTER_EOF;
break; }
break;
default: default:
return CLUSTER_ERROR; return CLUSTER_ERROR;
break; break;
} }
return nextCluster; return nextCluster;
} }
/* /*
writes value into the correct offset within a partition's FAT, based writes value into the correct offset within a partition's FAT, based
on the cluster number. on the cluster number.
*/ */
static bool _FAT_fat_writeFatEntry (PARTITION* partition, uint32_t cluster, uint32_t value) { static bool _FAT_fat_writeFatEntry ( PARTITION* partition, uint32_t cluster, uint32_t value )
sec_t sector; {
int offset; sec_t sector;
uint32_t oldValue; int offset;
uint32_t oldValue;
if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) if ( ( cluster < CLUSTER_FIRST ) || ( cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */ ) )
{ {
return false; return false;
} }
switch (partition->filesysType) switch ( partition->filesysType )
{ {
case FS_UNKNOWN: case FS_UNKNOWN:
return false; return false;
break; break;
case FS_FAT12: case FS_FAT12:
sector = partition->fat.fatStart + (((cluster * 3) / 2) / BYTES_PER_READ); sector = partition->fat.fatStart + ( ( ( cluster * 3 ) / 2 ) / BYTES_PER_READ );
offset = ((cluster * 3) / 2) % BYTES_PER_READ; offset = ( ( cluster * 3 ) / 2 ) % BYTES_PER_READ;
if (cluster & 0x01) { if ( cluster & 0x01 )
{
_FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(u8)); _FAT_cache_readLittleEndianValue ( partition->cache, &oldValue, sector, offset, sizeof( u8 ) );
value = (value << 4) | (oldValue & 0x0F); value = ( value << 4 ) | ( oldValue & 0x0F );
_FAT_cache_writeLittleEndianValue (partition->cache, value & 0xFF, sector, offset, sizeof(u8)); _FAT_cache_writeLittleEndianValue ( partition->cache, value & 0xFF, sector, offset, sizeof( u8 ) );
offset++; offset++;
if (offset >= BYTES_PER_READ) { if ( offset >= BYTES_PER_READ )
offset = 0; {
sector++; offset = 0;
} sector++;
}
_FAT_cache_writeLittleEndianValue (partition->cache, (value >> 8) & 0xFF, sector, offset, sizeof(u8)); _FAT_cache_writeLittleEndianValue ( partition->cache, ( value >> 8 ) & 0xFF, sector, offset, sizeof( u8 ) );
} else { }
else
{
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8)); _FAT_cache_writeLittleEndianValue ( partition->cache, value, sector, offset, sizeof( u8 ) );
offset++; offset++;
if (offset >= BYTES_PER_READ) { if ( offset >= BYTES_PER_READ )
offset = 0; {
sector++; offset = 0;
} sector++;
}
_FAT_cache_readLittleEndianValue (partition->cache, &oldValue, sector, offset, sizeof(u8)); _FAT_cache_readLittleEndianValue ( partition->cache, &oldValue, sector, offset, sizeof( u8 ) );
value = ((value >> 8) & 0x0F) | (oldValue & 0xF0); value = ( ( value >> 8 ) & 0x0F ) | ( oldValue & 0xF0 );
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u8)); _FAT_cache_writeLittleEndianValue ( partition->cache, value, sector, offset, sizeof( u8 ) );
} }
break; break;
case FS_FAT16: case FS_FAT16:
sector = partition->fat.fatStart + ((cluster << 1) / BYTES_PER_READ); sector = partition->fat.fatStart + ( ( cluster << 1 ) / BYTES_PER_READ );
offset = (cluster % (BYTES_PER_READ >> 1)) << 1; offset = ( cluster % ( BYTES_PER_READ >> 1 ) ) << 1;
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u16)); _FAT_cache_writeLittleEndianValue ( partition->cache, value, sector, offset, sizeof( u16 ) );
break; break;
case FS_FAT32: case FS_FAT32:
sector = partition->fat.fatStart + ((cluster << 2) / BYTES_PER_READ); sector = partition->fat.fatStart + ( ( cluster << 2 ) / BYTES_PER_READ );
offset = (cluster % (BYTES_PER_READ >> 2)) << 2; offset = ( cluster % ( BYTES_PER_READ >> 2 ) ) << 2;
_FAT_cache_writeLittleEndianValue (partition->cache, value, sector, offset, sizeof(u32)); _FAT_cache_writeLittleEndianValue ( partition->cache, value, sector, offset, sizeof( u32 ) );
break; break;
default: default:
return false; return false;
break; break;
} }
return true; return true;
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
@ -203,58 +216,67 @@ to end of file, links the input cluster to it then returns the
cluster number cluster number
If an error occurs, return CLUSTER_ERROR If an error occurs, return CLUSTER_ERROR
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) { uint32_t _FAT_fat_linkFreeCluster( PARTITION* partition, uint32_t cluster )
uint32_t firstFree; {
uint32_t curLink; uint32_t firstFree;
uint32_t lastCluster; uint32_t curLink;
bool loopedAroundFAT = false; uint32_t lastCluster;
bool loopedAroundFAT = false;
lastCluster = partition->fat.lastCluster; lastCluster = partition->fat.lastCluster;
if (cluster > lastCluster) { if ( cluster > lastCluster )
return CLUSTER_ERROR; {
} return CLUSTER_ERROR;
}
// Check if the cluster already has a link, and return it if so // Check if the cluster already has a link, and return it if so
curLink = _FAT_fat_nextCluster(partition, cluster); curLink = _FAT_fat_nextCluster( partition, cluster );
if ((curLink >= CLUSTER_FIRST) && (curLink <= lastCluster)) { if ( ( curLink >= CLUSTER_FIRST ) && ( curLink <= lastCluster ) )
return curLink; // Return the current link - don't allocate a new one {
} return curLink; // Return the current link - don't allocate a new one
}
// Get a free cluster // Get a free cluster
firstFree = partition->fat.firstFree; firstFree = partition->fat.firstFree;
// Start at first valid cluster // Start at first valid cluster
if (firstFree < CLUSTER_FIRST) { if ( firstFree < CLUSTER_FIRST )
firstFree = CLUSTER_FIRST; {
} firstFree = CLUSTER_FIRST;
}
// Search until a free cluster is found // Search until a free cluster is found
while (_FAT_fat_nextCluster(partition, firstFree) != CLUSTER_FREE) { while ( _FAT_fat_nextCluster( partition, firstFree ) != CLUSTER_FREE )
firstFree++; {
if (firstFree > lastCluster) { firstFree++;
if (loopedAroundFAT) { if ( firstFree > lastCluster )
// If couldn't get a free cluster then return an error {
partition->fat.firstFree = firstFree; if ( loopedAroundFAT )
return CLUSTER_ERROR; {
} else { // If couldn't get a free cluster then return an error
// Try looping back to the beginning of the FAT partition->fat.firstFree = firstFree;
// This was suggested by loopy return CLUSTER_ERROR;
firstFree = CLUSTER_FIRST; }
loopedAroundFAT = true; else
} {
} // Try looping back to the beginning of the FAT
} // This was suggested by loopy
partition->fat.firstFree = firstFree; firstFree = CLUSTER_FIRST;
loopedAroundFAT = true;
}
}
}
partition->fat.firstFree = firstFree;
if ((cluster >= CLUSTER_FIRST) && (cluster < lastCluster)) if ( ( cluster >= CLUSTER_FIRST ) && ( cluster < lastCluster ) )
{ {
// Update the linked from FAT entry // Update the linked from FAT entry
_FAT_fat_writeFatEntry (partition, cluster, firstFree); _FAT_fat_writeFatEntry ( partition, cluster, firstFree );
} }
// Create the linked to FAT entry // Create the linked to FAT entry
_FAT_fat_writeFatEntry (partition, firstFree, CLUSTER_EOF); _FAT_fat_writeFatEntry ( partition, firstFree, CLUSTER_EOF );
return firstFree; return firstFree;
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
@ -263,27 +285,30 @@ to end of file, links the input cluster to it, clears the new
cluster to 0 valued bytes, then returns the cluster number cluster to 0 valued bytes, then returns the cluster number
If an error occurs, return CLUSTER_ERROR If an error occurs, return CLUSTER_ERROR
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster) { uint32_t _FAT_fat_linkFreeClusterCleared ( PARTITION* partition, uint32_t cluster )
uint32_t newCluster; {
uint32_t i; uint32_t newCluster;
uint8_t emptySector[BYTES_PER_READ]; uint32_t i;
uint8_t emptySector[BYTES_PER_READ];
// Link the cluster // Link the cluster
newCluster = _FAT_fat_linkFreeCluster(partition, cluster); newCluster = _FAT_fat_linkFreeCluster( partition, cluster );
if (newCluster == CLUSTER_FREE || newCluster == CLUSTER_ERROR) { if ( newCluster == CLUSTER_FREE || newCluster == CLUSTER_ERROR )
return CLUSTER_ERROR; {
} return CLUSTER_ERROR;
}
// Clear all the sectors within the cluster // Clear all the sectors within the cluster
memset (emptySector, 0, BYTES_PER_READ); memset ( emptySector, 0, BYTES_PER_READ );
for (i = 0; i < partition->sectorsPerCluster; i++) { for ( i = 0; i < partition->sectorsPerCluster; i++ )
_FAT_cache_writeSectors (partition->cache, {
_FAT_fat_clusterToSector (partition, newCluster) + i, _FAT_cache_writeSectors ( partition->cache,
1, emptySector); _FAT_fat_clusterToSector ( partition, newCluster ) + i,
} 1, emptySector );
}
return newCluster; return newCluster;
} }
@ -291,29 +316,32 @@ uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster
_FAT_fat_clearLinks _FAT_fat_clearLinks
frees any cluster used by a file frees any cluster used by a file
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) { bool _FAT_fat_clearLinks ( PARTITION* partition, uint32_t cluster )
uint32_t nextCluster; {
uint32_t nextCluster;
if ((cluster < CLUSTER_FIRST) || (cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */)) if ( ( cluster < CLUSTER_FIRST ) || ( cluster > partition->fat.lastCluster /* This will catch CLUSTER_ERROR */ ) )
return false; return false;
// If this clears up more space in the FAT before the current free pointer, move it backwards // If this clears up more space in the FAT before the current free pointer, move it backwards
if (cluster < partition->fat.firstFree) { if ( cluster < partition->fat.firstFree )
partition->fat.firstFree = cluster; {
} partition->fat.firstFree = cluster;
}
while ((cluster != CLUSTER_EOF) && (cluster != CLUSTER_FREE) && (cluster != CLUSTER_ERROR)) { while ( ( cluster != CLUSTER_EOF ) && ( cluster != CLUSTER_FREE ) && ( cluster != CLUSTER_ERROR ) )
// Store next cluster before erasing the link {
nextCluster = _FAT_fat_nextCluster (partition, cluster); // Store next cluster before erasing the link
nextCluster = _FAT_fat_nextCluster ( partition, cluster );
// Erase the link // Erase the link
_FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); _FAT_fat_writeFatEntry ( partition, cluster, CLUSTER_FREE );
// Move onto next cluster // Move onto next cluster
cluster = nextCluster; cluster = nextCluster;
} }
return true; return true;
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
@ -324,60 +352,71 @@ If chainLength is 1, the first cluster is kept and the rest are
dropped, and so on. dropped, and so on.
Return the last cluster left in the chain. Return the last cluster left in the chain.
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength) { uint32_t _FAT_fat_trimChain ( PARTITION* partition, uint32_t startCluster, unsigned int chainLength )
uint32_t nextCluster; {
uint32_t nextCluster;
if (chainLength == 0) { if ( chainLength == 0 )
// Drop the entire chain {
_FAT_fat_clearLinks (partition, startCluster); // Drop the entire chain
return CLUSTER_FREE; _FAT_fat_clearLinks ( partition, startCluster );
} else { return CLUSTER_FREE;
// Find the last cluster in the chain, and the one after it }
chainLength--; else
nextCluster = _FAT_fat_nextCluster (partition, startCluster); {
while ((chainLength > 0) && (nextCluster != CLUSTER_FREE) && (nextCluster != CLUSTER_EOF)) { // Find the last cluster in the chain, and the one after it
chainLength--; chainLength--;
startCluster = nextCluster; nextCluster = _FAT_fat_nextCluster ( partition, startCluster );
nextCluster = _FAT_fat_nextCluster (partition, startCluster); while ( ( chainLength > 0 ) && ( nextCluster != CLUSTER_FREE ) && ( nextCluster != CLUSTER_EOF ) )
} {
chainLength--;
startCluster = nextCluster;
nextCluster = _FAT_fat_nextCluster ( partition, startCluster );
}
// Drop all clusters after the last in the chain // Drop all clusters after the last in the chain
if (nextCluster != CLUSTER_FREE && nextCluster != CLUSTER_EOF) { if ( nextCluster != CLUSTER_FREE && nextCluster != CLUSTER_EOF )
_FAT_fat_clearLinks (partition, nextCluster); {
} _FAT_fat_clearLinks ( partition, nextCluster );
}
// Mark the last cluster in the chain as the end of the file // Mark the last cluster in the chain as the end of the file
_FAT_fat_writeFatEntry (partition, startCluster, CLUSTER_EOF); _FAT_fat_writeFatEntry ( partition, startCluster, CLUSTER_EOF );
return startCluster; return startCluster;
} }
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
_FAT_fat_lastCluster _FAT_fat_lastCluster
Trace the cluster links until the last one is found Trace the cluster links until the last one is found
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster) { uint32_t _FAT_fat_lastCluster ( PARTITION* partition, uint32_t cluster )
while ((_FAT_fat_nextCluster(partition, cluster) != CLUSTER_FREE) && (_FAT_fat_nextCluster(partition, cluster) != CLUSTER_EOF)) { {
cluster = _FAT_fat_nextCluster(partition, cluster); while ( ( _FAT_fat_nextCluster( partition, cluster ) != CLUSTER_FREE ) && ( _FAT_fat_nextCluster( partition, cluster ) != CLUSTER_EOF ) )
} {
return cluster; cluster = _FAT_fat_nextCluster( partition, cluster );
}
return cluster;
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
_FAT_fat_freeClusterCount _FAT_fat_freeClusterCount
Return the number of free clusters available Return the number of free clusters available
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
unsigned int _FAT_fat_freeClusterCount (PARTITION* partition) { unsigned int _FAT_fat_freeClusterCount ( PARTITION* partition )
unsigned int count = 0; {
uint32_t curCluster; unsigned int count = 0;
uint32_t curCluster;
for (curCluster = CLUSTER_FIRST; curCluster <= partition->fat.lastCluster; curCluster++) { for ( curCluster = CLUSTER_FIRST; curCluster <= partition->fat.lastCluster; curCluster++ )
if (_FAT_fat_nextCluster(partition, curCluster) == CLUSTER_FREE) { {
count++; if ( _FAT_fat_nextCluster( partition, curCluster ) == CLUSTER_FREE )
} {
} count++;
}
}
return count; return count;
} }

View File

@ -33,38 +33,40 @@
#include "common.h" #include "common.h"
#include "partition.h" #include "partition.h"
#define CLUSTER_EOF_16 0xFFFF #define CLUSTER_EOF_16 0xFFFF
#define CLUSTER_EOF 0x0FFFFFFF #define CLUSTER_EOF 0x0FFFFFFF
#define CLUSTER_FREE 0x00000000 #define CLUSTER_FREE 0x00000000
#define CLUSTER_ROOT 0x00000000 #define CLUSTER_ROOT 0x00000000
#define CLUSTER_FIRST 0x00000002 #define CLUSTER_FIRST 0x00000002
#define CLUSTER_ERROR 0xFFFFFFFF #define CLUSTER_ERROR 0xFFFFFFFF
#define CLUSTERS_PER_FAT12 4085 #define CLUSTERS_PER_FAT12 4085
#define CLUSTERS_PER_FAT16 65525 #define CLUSTERS_PER_FAT16 65525
uint32_t _FAT_fat_nextCluster(PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_nextCluster( PARTITION* partition, uint32_t cluster );
uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_linkFreeCluster( PARTITION* partition, uint32_t cluster );
uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_linkFreeClusterCleared ( PARTITION* partition, uint32_t cluster );
bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster); bool _FAT_fat_clearLinks ( PARTITION* partition, uint32_t cluster );
uint32_t _FAT_fat_trimChain (PARTITION* partition, uint32_t startCluster, unsigned int chainLength); uint32_t _FAT_fat_trimChain ( PARTITION* partition, uint32_t startCluster, unsigned int chainLength );
uint32_t _FAT_fat_lastCluster (PARTITION* partition, uint32_t cluster); uint32_t _FAT_fat_lastCluster ( PARTITION* partition, uint32_t cluster );
unsigned int _FAT_fat_freeClusterCount (PARTITION* partition); unsigned int _FAT_fat_freeClusterCount ( PARTITION* partition );
static inline sec_t _FAT_fat_clusterToSector (PARTITION* partition, uint32_t cluster) { static inline sec_t _FAT_fat_clusterToSector ( PARTITION* partition, uint32_t cluster )
return (cluster >= CLUSTER_FIRST) ? {
((cluster - CLUSTER_FIRST) * (sec_t)partition->sectorsPerCluster) + partition->dataStart : return ( cluster >= CLUSTER_FIRST ) ?
partition->rootDirStart; ( ( cluster - CLUSTER_FIRST ) * ( sec_t )partition->sectorsPerCluster ) + partition->dataStart :
partition->rootDirStart;
} }
static inline bool _FAT_fat_isValidCluster (PARTITION* partition, uint32_t cluster) { static inline bool _FAT_fat_isValidCluster ( PARTITION* partition, uint32_t cluster )
return (cluster >= CLUSTER_FIRST) && (cluster <= partition->fat.lastCluster /* This will catch CLUSTER_ERROR */); {
return ( cluster >= CLUSTER_FIRST ) && ( cluster <= partition->fat.lastCluster /* This will catch CLUSTER_ERROR */ );
} }
#endif // _FAT_H #endif // _FAT_H

View File

@ -3,7 +3,7 @@
Conversion of file time and date values to various other types Conversion of file time and date values to various other types
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
@ -40,68 +40,73 @@
#define MAX_DAY 31 #define MAX_DAY 31
#define MIN_DAY 1 #define MIN_DAY 1
uint16_t _FAT_filetime_getTimeFromRTC (void) { uint16_t _FAT_filetime_getTimeFromRTC ( void )
{
#ifdef USE_RTC_TIME #ifdef USE_RTC_TIME
struct tm timeParts; struct tm timeParts;
time_t epochTime; time_t epochTime;
if (time(&epochTime) == (time_t)-1) {
return 0;
}
localtime_r(&epochTime, &timeParts);
// Check that the values are all in range. if ( time( &epochTime ) == ( time_t ) - 1 )
// If they are not, return 0 (no timestamp) {
if ((timeParts.tm_hour < 0) || (timeParts.tm_hour > MAX_HOUR)) return 0; return 0;
if ((timeParts.tm_min < 0) || (timeParts.tm_min > MAX_MINUTE)) return 0; }
if ((timeParts.tm_sec < 0) || (timeParts.tm_sec > MAX_SECOND)) return 0; localtime_r( &epochTime, &timeParts );
return ( // Check that the values are all in range.
((timeParts.tm_hour & 0x1F) << 11) | // If they are not, return 0 (no timestamp)
((timeParts.tm_min & 0x3F) << 5) | if ( ( timeParts.tm_hour < 0 ) || ( timeParts.tm_hour > MAX_HOUR ) ) return 0;
((timeParts.tm_sec >> 1) & 0x1F) if ( ( timeParts.tm_min < 0 ) || ( timeParts.tm_min > MAX_MINUTE ) ) return 0;
); if ( ( timeParts.tm_sec < 0 ) || ( timeParts.tm_sec > MAX_SECOND ) ) return 0;
return (
( ( timeParts.tm_hour & 0x1F ) << 11 ) |
( ( timeParts.tm_min & 0x3F ) << 5 ) |
( ( timeParts.tm_sec >> 1 ) & 0x1F )
);
#else #else
return 0; return 0;
#endif #endif
} }
uint16_t _FAT_filetime_getDateFromRTC (void) { uint16_t _FAT_filetime_getDateFromRTC ( void )
{
#ifdef USE_RTC_TIME #ifdef USE_RTC_TIME
struct tm timeParts; struct tm timeParts;
time_t epochTime; time_t epochTime;
if (time(&epochTime) == (time_t)-1) {
return 0;
}
localtime_r(&epochTime, &timeParts);
if ((timeParts.tm_mon < MIN_MONTH) || (timeParts.tm_mon > MAX_MONTH)) return 0; if ( time( &epochTime ) == ( time_t ) - 1 )
if ((timeParts.tm_mday < MIN_DAY) || (timeParts.tm_mday > MAX_DAY)) return 0; {
return 0;
return ( }
(((timeParts.tm_year - 80) & 0x7F) <<9) | // Adjust for MS-FAT base year (1980 vs 1900 for tm_year) localtime_r( &epochTime, &timeParts );
(((timeParts.tm_mon + 1) & 0xF) << 5) |
(timeParts.tm_mday & 0x1F) if ( ( timeParts.tm_mon < MIN_MONTH ) || ( timeParts.tm_mon > MAX_MONTH ) ) return 0;
); if ( ( timeParts.tm_mday < MIN_DAY ) || ( timeParts.tm_mday > MAX_DAY ) ) return 0;
return (
( ( ( timeParts.tm_year - 80 ) & 0x7F ) << 9 ) | // Adjust for MS-FAT base year (1980 vs 1900 for tm_year)
( ( ( timeParts.tm_mon + 1 ) & 0xF ) << 5 ) |
( timeParts.tm_mday & 0x1F )
);
#else #else
return 0; return 0;
#endif #endif
} }
time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d) { time_t _FAT_filetime_to_time_t ( uint16_t t, uint16_t d )
struct tm timeParts; {
struct tm timeParts;
timeParts.tm_hour = t >> 11; timeParts.tm_hour = t >> 11;
timeParts.tm_min = (t >> 5) & 0x3F; timeParts.tm_min = ( t >> 5 ) & 0x3F;
timeParts.tm_sec = (t & 0x1F) << 1; timeParts.tm_sec = ( t & 0x1F ) << 1;
timeParts.tm_mday = d & 0x1F; timeParts.tm_mday = d & 0x1F;
timeParts.tm_mon = ((d >> 5) & 0x0F) - 1; timeParts.tm_mon = ( ( d >> 5 ) & 0x0F ) - 1;
timeParts.tm_year = (d >> 9) + 80; timeParts.tm_year = ( d >> 9 ) + 80;
timeParts.tm_isdst = 0; timeParts.tm_isdst = 0;
return mktime(&timeParts); return mktime( &timeParts );
} }

View File

@ -32,10 +32,10 @@
#include "common.h" #include "common.h"
#include <sys/types.h> #include <sys/types.h>
uint16_t _FAT_filetime_getTimeFromRTC (void); uint16_t _FAT_filetime_getTimeFromRTC ( void );
uint16_t _FAT_filetime_getDateFromRTC (void); uint16_t _FAT_filetime_getDateFromRTC ( void );
time_t _FAT_filetime_to_time_t (uint16_t t, uint16_t d); time_t _FAT_filetime_to_time_t ( uint16_t t, uint16_t d );
#endif // _FILETIME_H #endif // _FILETIME_H

View File

@ -1,6 +1,6 @@
/* /*
libfat.c libfat.c
Simple functionality for startup, mounting and unmounting of FAT-based devices. Simple functionality for startup, mounting and unmounting of FAT-based devices.
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 Michael "Chishm" Chisholm
@ -38,160 +38,178 @@
#include "mem_allocate.h" #include "mem_allocate.h"
#include "disc_fat.h" #include "disc_fat.h"
static const devoptab_t dotab_fat = { static const devoptab_t dotab_fat =
"fat", {
sizeof (FILE_STRUCT), "fat",
_FAT_open_r, sizeof ( FILE_STRUCT ),
_FAT_close_r, _FAT_open_r,
_FAT_write_r, _FAT_close_r,
_FAT_read_r, _FAT_write_r,
_FAT_seek_r, _FAT_read_r,
_FAT_fstat_r, _FAT_seek_r,
_FAT_stat_r, _FAT_fstat_r,
_FAT_link_r, _FAT_stat_r,
_FAT_unlink_r, _FAT_link_r,
_FAT_chdir_r, _FAT_unlink_r,
_FAT_rename_r, _FAT_chdir_r,
_FAT_mkdir_r, _FAT_rename_r,
sizeof (DIR_STATE_STRUCT), _FAT_mkdir_r,
_FAT_diropen_r, sizeof ( DIR_STATE_STRUCT ),
_FAT_dirreset_r, _FAT_diropen_r,
_FAT_dirnext_r, _FAT_dirreset_r,
_FAT_dirclose_r, _FAT_dirnext_r,
_FAT_statvfs_r, _FAT_dirclose_r,
_FAT_ftruncate_r, _FAT_statvfs_r,
_FAT_fsync_r, _FAT_ftruncate_r,
NULL /* Device data */ _FAT_fsync_r,
NULL /* Device data */
}; };
bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage) { bool fatMount ( const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage )
PARTITION* partition; {
devoptab_t* devops; PARTITION* partition;
char* nameCopy; devoptab_t* devops;
char* nameCopy;
if(!interface->startup()) if ( !interface->startup() )
return false; return false;
if(!interface->isInserted()) { if ( !interface->isInserted() )
interface->shutdown(); {
return false; interface->shutdown();
} return false;
}
devops = _FAT_mem_allocate (sizeof(devoptab_t) + strlen(name) + 1); devops = _FAT_mem_allocate ( sizeof( devoptab_t ) + strlen( name ) + 1 );
if (!devops) { if ( !devops )
interface->shutdown(); {
return false; interface->shutdown();
} return false;
// Use the space allocated at the end of the devoptab struct for storing the name }
nameCopy = (char*)(devops+1); // Use the space allocated at the end of the devoptab struct for storing the name
nameCopy = ( char* )( devops + 1 );
// Initialize the file system // Initialize the file system
partition = _FAT_partition_constructor (interface, cacheSize, SectorsPerPage, startSector); partition = _FAT_partition_constructor ( interface, cacheSize, SectorsPerPage, startSector );
if (!partition) { if ( !partition )
_FAT_mem_free (devops); {
interface->shutdown(); _FAT_mem_free ( devops );
return false; interface->shutdown();
} return false;
}
// Add an entry for this device to the devoptab table // Add an entry for this device to the devoptab table
memcpy (devops, &dotab_fat, sizeof(dotab_fat)); memcpy ( devops, &dotab_fat, sizeof( dotab_fat ) );
strcpy (nameCopy, name); strcpy ( nameCopy, name );
devops->name = nameCopy; devops->name = nameCopy;
devops->deviceData = partition; devops->deviceData = partition;
AddDevice (devops); AddDevice ( devops );
return true; return true;
} }
bool fatMountSimple (const char* name, const DISC_INTERFACE* interface) { bool fatMountSimple ( const char* name, const DISC_INTERFACE* interface )
return fatMount (name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE); {
return fatMount ( name, interface, 0, DEFAULT_CACHE_PAGES, DEFAULT_SECTORS_PAGE );
} }
void fatUnmount (const char* name) { void fatUnmount ( const char* name )
devoptab_t *devops; {
PARTITION* partition; devoptab_t *devops;
const DISC_INTERFACE *disc; PARTITION* partition;
const DISC_INTERFACE *disc;
devops = (devoptab_t*)GetDeviceOpTab (name); devops = ( devoptab_t* )GetDeviceOpTab ( name );
if (!devops) { if ( !devops )
return; {
} return;
}
// Perform a quick check to make sure we're dealing with a libfat controlled device // Perform a quick check to make sure we're dealing with a libfat controlled device
if (devops->open_r != dotab_fat.open_r) { if ( devops->open_r != dotab_fat.open_r )
return; {
} return;
}
if (RemoveDevice (name) == -1) { if ( RemoveDevice ( name ) == -1 )
return; {
} return;
}
partition = (PARTITION*)devops->deviceData; partition = ( PARTITION* )devops->deviceData;
disc = partition->disc; disc = partition->disc;
_FAT_partition_destructor (partition); _FAT_partition_destructor ( partition );
_FAT_mem_free (devops); _FAT_mem_free ( devops );
disc->shutdown(); disc->shutdown();
} }
bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice) { bool fatInit ( uint32_t cacheSize, bool setAsDefaultDevice )
int i; {
int defaultDevice = -1; int i;
const DISC_INTERFACE *disc; int defaultDevice = -1;
const DISC_INTERFACE *disc;
for (i = 0; for ( i = 0;
_FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL;
i++) i++ )
{ {
disc = _FAT_disc_interfaces[i].getInterface(); disc = _FAT_disc_interfaces[i].getInterface();
if (fatMount (_FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE)) { if ( fatMount ( _FAT_disc_interfaces[i].name, disc, 0, cacheSize, DEFAULT_SECTORS_PAGE ) )
// The first device to successfully mount is set as the default {
if (defaultDevice < 0) { // The first device to successfully mount is set as the default
defaultDevice = i; if ( defaultDevice < 0 )
} {
} defaultDevice = i;
} }
}
}
if (defaultDevice < 0) { if ( defaultDevice < 0 )
// None of our devices mounted {
return false; // None of our devices mounted
} return false;
}
if (setAsDefaultDevice) { if ( setAsDefaultDevice )
char filePath[MAXPATHLEN * 2]; {
strcpy (filePath, _FAT_disc_interfaces[defaultDevice].name); char filePath[MAXPATHLEN * 2];
strcat (filePath, ":/"); strcpy ( filePath, _FAT_disc_interfaces[defaultDevice].name );
strcat ( filePath, ":/" );
#ifdef ARGV_MAGIC #ifdef ARGV_MAGIC
if ( __system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 && strrchr( __system_argv->argv[0], '/' )!=NULL ) { if ( __system_argv->argvMagic == ARGV_MAGIC && __system_argv->argc >= 1 && strrchr( __system_argv->argv[0], '/' ) != NULL )
// Check the app's path against each of our mounted devices, to see {
// if we can support it. If so, change to that path. // Check the app's path against each of our mounted devices, to see
for (i = 0; // if we can support it. If so, change to that path.
_FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL; for ( i = 0;
i++) _FAT_disc_interfaces[i].name != NULL && _FAT_disc_interfaces[i].getInterface != NULL;
{ i++ )
if ( !strncasecmp( __system_argv->argv[0], _FAT_disc_interfaces[i].name, {
strlen(_FAT_disc_interfaces[i].name))) if ( !strncasecmp( __system_argv->argv[0], _FAT_disc_interfaces[i].name,
{ strlen( _FAT_disc_interfaces[i].name ) ) )
char *lastSlash; {
strcpy(filePath, __system_argv->argv[0]); char *lastSlash;
lastSlash = strrchr( filePath, '/' ); strcpy( filePath, __system_argv->argv[0] );
lastSlash = strrchr( filePath, '/' );
if ( NULL != lastSlash) { if ( NULL != lastSlash )
if ( *(lastSlash - 1) == ':') lastSlash++; {
*lastSlash = 0; if ( *( lastSlash - 1 ) == ':' ) lastSlash++;
} *lastSlash = 0;
} }
} }
} }
}
#endif #endif
chdir (filePath); chdir ( filePath );
} }
return true; return true;
} }
bool fatInitDefault (void) { bool fatInitDefault ( void )
return fatInit (DEFAULT_CACHE_PAGES, true); {
return fatInit ( DEFAULT_CACHE_PAGES, true );
} }

View File

@ -1,9 +1,9 @@
#ifndef __LIBFATVERSION_H__ #ifndef __LIBFATVERSION_H__
#define __LIBFATVERSION_H__ #define __LIBFATVERSION_H__
#define _LIBFAT_MAJOR_ 1 #define _LIBFAT_MAJOR_ 1
#define _LIBFAT_MINOR_ 0 #define _LIBFAT_MINOR_ 0
#define _LIBFAT_PATCH_ 7 #define _LIBFAT_PATCH_ 7
#define _LIBFAT_STRING "libFAT Release 1.0.7" #define _LIBFAT_STRING "libFAT Release 1.0.7"

View File

@ -33,24 +33,24 @@
#ifdef USE_LWP_LOCK #ifdef USE_LWP_LOCK
static inline void _FAT_lock_init(mutex_t *mutex) static inline void _FAT_lock_init( mutex_t *mutex )
{ {
LWP_MutexInit(mutex, false); LWP_MutexInit( mutex, false );
} }
static inline void _FAT_lock_deinit(mutex_t *mutex) static inline void _FAT_lock_deinit( mutex_t *mutex )
{ {
LWP_MutexDestroy(*mutex); LWP_MutexDestroy( *mutex );
} }
static inline void _FAT_lock(mutex_t *mutex) static inline void _FAT_lock( mutex_t *mutex )
{ {
LWP_MutexLock(*mutex); LWP_MutexLock( *mutex );
} }
static inline void _FAT_unlock(mutex_t *mutex) static inline void _FAT_unlock( mutex_t *mutex )
{ {
LWP_MutexUnlock(*mutex); LWP_MutexUnlock( *mutex );
} }
#else #else
@ -60,24 +60,24 @@ static inline void _FAT_unlock(mutex_t *mutex)
typedef int mutex_t; typedef int mutex_t;
#endif #endif
static inline void _FAT_lock_init(mutex_t *mutex) static inline void _FAT_lock_init( mutex_t *mutex )
{ {
return; return;
} }
static inline void _FAT_lock_deinit(mutex_t *mutex) static inline void _FAT_lock_deinit( mutex_t *mutex )
{ {
return; return;
} }
static inline void _FAT_lock(mutex_t *mutex) static inline void _FAT_lock( mutex_t *mutex )
{ {
return; return;
} }
static inline void _FAT_unlock(mutex_t *mutex) static inline void _FAT_unlock( mutex_t *mutex )
{ {
return; return;
} }
#endif // USE_LWP_LOCK #endif // USE_LWP_LOCK

View File

@ -33,17 +33,20 @@
#include <malloc.h> #include <malloc.h>
static inline void* _FAT_mem_allocate (size_t size) { static inline void* _FAT_mem_allocate ( size_t size )
return malloc (size); {
return malloc ( size );
} }
static inline void* _FAT_mem_align (size_t size) { static inline void* _FAT_mem_align ( size_t size )
{
return memalign (32, size); return memalign ( 32, size );
} }
static inline void _FAT_mem_free (void* mem) { static inline void _FAT_mem_free ( void* mem )
free (mem); {
free ( mem );
} }
#endif // _MEM_ALLOCATE_H #endif // _MEM_ALLOCATE_H

View File

@ -50,263 +50,298 @@ Data offsets
*/ */
// BIOS Parameter Block offsets // BIOS Parameter Block offsets
enum BPB { enum BPB
BPB_jmpBoot = 0x00, {
BPB_OEMName = 0x03, BPB_jmpBoot = 0x00,
// BIOS Parameter Block BPB_OEMName = 0x03,
BPB_bytesPerSector = 0x0B, // BIOS Parameter Block
BPB_sectorsPerCluster = 0x0D, BPB_bytesPerSector = 0x0B,
BPB_reservedSectors = 0x0E, BPB_sectorsPerCluster = 0x0D,
BPB_numFATs = 0x10, BPB_reservedSectors = 0x0E,
BPB_rootEntries = 0x11, BPB_numFATs = 0x10,
BPB_numSectorsSmall = 0x13, BPB_rootEntries = 0x11,
BPB_mediaDesc = 0x15, BPB_numSectorsSmall = 0x13,
BPB_sectorsPerFAT = 0x16, BPB_mediaDesc = 0x15,
BPB_sectorsPerTrk = 0x18, BPB_sectorsPerFAT = 0x16,
BPB_numHeads = 0x1A, BPB_sectorsPerTrk = 0x18,
BPB_numHiddenSectors = 0x1C, BPB_numHeads = 0x1A,
BPB_numSectors = 0x20, BPB_numHiddenSectors = 0x1C,
// Ext BIOS Parameter Block for FAT16 BPB_numSectors = 0x20,
BPB_FAT16_driveNumber = 0x24, // Ext BIOS Parameter Block for FAT16
BPB_FAT16_reserved1 = 0x25, BPB_FAT16_driveNumber = 0x24,
BPB_FAT16_extBootSig = 0x26, BPB_FAT16_reserved1 = 0x25,
BPB_FAT16_volumeID = 0x27, BPB_FAT16_extBootSig = 0x26,
BPB_FAT16_volumeLabel = 0x2B, BPB_FAT16_volumeID = 0x27,
BPB_FAT16_fileSysType = 0x36, BPB_FAT16_volumeLabel = 0x2B,
// Bootcode BPB_FAT16_fileSysType = 0x36,
BPB_FAT16_bootCode = 0x3E, // Bootcode
// FAT32 extended block BPB_FAT16_bootCode = 0x3E,
BPB_FAT32_sectorsPerFAT32 = 0x24, // FAT32 extended block
BPB_FAT32_extFlags = 0x28, BPB_FAT32_sectorsPerFAT32 = 0x24,
BPB_FAT32_fsVer = 0x2A, BPB_FAT32_extFlags = 0x28,
BPB_FAT32_rootClus = 0x2C, BPB_FAT32_fsVer = 0x2A,
BPB_FAT32_fsInfo = 0x30, BPB_FAT32_rootClus = 0x2C,
BPB_FAT32_bkBootSec = 0x32, BPB_FAT32_fsInfo = 0x30,
// Ext BIOS Parameter Block for FAT32 BPB_FAT32_bkBootSec = 0x32,
BPB_FAT32_driveNumber = 0x40, // Ext BIOS Parameter Block for FAT32
BPB_FAT32_reserved1 = 0x41, BPB_FAT32_driveNumber = 0x40,
BPB_FAT32_extBootSig = 0x42, BPB_FAT32_reserved1 = 0x41,
BPB_FAT32_volumeID = 0x43, BPB_FAT32_extBootSig = 0x42,
BPB_FAT32_volumeLabel = 0x47, BPB_FAT32_volumeID = 0x43,
BPB_FAT32_fileSysType = 0x52, BPB_FAT32_volumeLabel = 0x47,
// Bootcode BPB_FAT32_fileSysType = 0x52,
BPB_FAT32_bootCode = 0x5A, // Bootcode
BPB_bootSig_55 = 0x1FE, BPB_FAT32_bootCode = 0x5A,
BPB_bootSig_AA = 0x1FF BPB_bootSig_55 = 0x1FE,
BPB_bootSig_AA = 0x1FF
}; };
static const char FAT_SIG[3] = {'F', 'A', 'T'}; static const char FAT_SIG[3] = {'F', 'A', 'T'};
sec_t FindFirstValidPartition(const DISC_INTERFACE* disc) sec_t FindFirstValidPartition( const DISC_INTERFACE* disc )
{ {
uint8_t part_table[16*4]; uint8_t part_table[16*4];
uint8_t *ptr; uint8_t *ptr;
int i; int i;
uint8_t sectorBuffer[BYTES_PER_READ] = {0}; uint8_t sectorBuffer[BYTES_PER_READ] = {0};
// Read first sector of disc // Read first sector of disc
if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) { if ( !_FAT_disc_readSectors ( disc, 0, 1, sectorBuffer ) )
return 0; {
} return 0;
}
memcpy(part_table,sectorBuffer+0x1BE,16*4); memcpy( part_table, sectorBuffer + 0x1BE, 16*4 );
ptr = part_table; ptr = part_table;
for(i=0;i<4;i++,ptr+=16) { for ( i = 0; i < 4; i++, ptr += 16 )
sec_t part_lba = u8array_to_u32(ptr, 0x8); {
sec_t part_lba = u8array_to_u32( ptr, 0x8 );
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || if ( !memcmp( sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) ||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { !memcmp( sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) )
return part_lba; {
} return part_lba;
}
if(ptr[4]==0) continue; if ( ptr[4] == 0 ) continue;
if(ptr[4]==0x0F) { if ( ptr[4] == 0x0F )
sec_t part_lba2=part_lba; {
sec_t next_lba2=0; sec_t part_lba2 = part_lba;
int n; sec_t next_lba2 = 0;
int n;
for(n=0;n<8;n++) // max 8 logic partitions for ( n = 0; n < 8; n++ ) // max 8 logic partitions
{ {
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) return 0; if ( !_FAT_disc_readSectors ( disc, part_lba + next_lba2, 1, sectorBuffer ) ) return 0;
part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ; part_lba2 = part_lba + next_lba2 + u8array_to_u32( sectorBuffer, 0x1C6 ) ;
next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6); next_lba2 = u8array_to_u32( sectorBuffer, 0x1D6 );
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) return 0; if ( !_FAT_disc_readSectors ( disc, part_lba2, 1, sectorBuffer ) ) return 0;
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || if ( !memcmp( sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) ||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) !memcmp( sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) )
{ {
return part_lba2; return part_lba2;
} }
if(next_lba2==0) break; if ( next_lba2 == 0 ) break;
} }
} else { }
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) return 0; else
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) || {
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { if ( !_FAT_disc_readSectors ( disc, part_lba, 1, sectorBuffer ) ) return 0;
return part_lba; if ( !memcmp( sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) ||
} !memcmp( sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) )
} {
} return part_lba;
return 0; }
}
}
return 0;
} }
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) { PARTITION* _FAT_partition_constructor ( const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector )
PARTITION* partition; {
uint8_t sectorBuffer[BYTES_PER_READ] = {0}; PARTITION* partition;
uint8_t sectorBuffer[BYTES_PER_READ] = {0};
// Read first sector of disc // Read first sector of disc
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { if ( !_FAT_disc_readSectors ( disc, startSector, 1, sectorBuffer ) )
return NULL; {
} return NULL;
}
// Make sure it is a valid MBR or boot sector // Make sure it is a valid MBR or boot sector
if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { if ( ( sectorBuffer[BPB_bootSig_55] != 0x55 ) || ( sectorBuffer[BPB_bootSig_AA] != 0xAA ) )
return NULL; {
} return NULL;
}
if (startSector != 0) { if ( startSector != 0 )
// We're told where to start the partition, so just accept it {
} else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // We're told where to start the partition, so just accept it
// Check if there is a FAT string, which indicates this is a boot sector }
startSector = 0; else if ( !memcmp( sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) )
} else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { {
// Check for FAT32 // Check if there is a FAT string, which indicates this is a boot sector
startSector = 0; startSector = 0;
} else { }
startSector = FindFirstValidPartition(disc); else if ( !memcmp( sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) )
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { {
return NULL; // Check for FAT32
} startSector = 0;
} }
else
{
startSector = FindFirstValidPartition( disc );
if ( !_FAT_disc_readSectors ( disc, startSector, 1, sectorBuffer ) )
{
return NULL;
}
}
// Now verify that this is indeed a FAT partition // Now verify that this is indeed a FAT partition
if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && if ( memcmp( sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) &&
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) memcmp( sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof( FAT_SIG ) ) )
{ {
return NULL; return NULL;
} }
// check again for the last two cases to make sure that we really have a FAT filesystem here // check again for the last two cases to make sure that we really have a FAT filesystem here
// and won't corrupt any data // and won't corrupt any data
if(memcmp(sectorBuffer + BPB_FAT16_fileSysType, "FAT", 3) != 0 && memcmp(sectorBuffer + BPB_FAT32_fileSysType, "FAT32", 5) != 0) if ( memcmp( sectorBuffer + BPB_FAT16_fileSysType, "FAT", 3 ) != 0 && memcmp( sectorBuffer + BPB_FAT32_fileSysType, "FAT32", 5 ) != 0 )
{ {
return NULL; return NULL;
} }
partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); partition = ( PARTITION* ) _FAT_mem_allocate ( sizeof( PARTITION ) );
if (partition == NULL) { if ( partition == NULL )
return NULL; {
} return NULL;
}
_FAT_startSector = startSector; _FAT_startSector = startSector;
// Init the partition lock // Init the partition lock
_FAT_lock_init(&partition->lock); _FAT_lock_init( &partition->lock );
// Set partition's disc interface // Set partition's disc interface
partition->disc = disc; partition->disc = disc;
// Store required information about the file system // Store required information about the file system
partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); partition->fat.sectorsPerFat = u8array_to_u16( sectorBuffer, BPB_sectorsPerFAT );
if (partition->fat.sectorsPerFat == 0) { if ( partition->fat.sectorsPerFat == 0 )
partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); {
} partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32 );
}
partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall );
if (partition->numberOfSectors == 0) { if ( partition->numberOfSectors == 0 )
partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); {
} partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors );
}
partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes
partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ; partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16( sectorBuffer, BPB_bytesPerSector ) / BYTES_PER_READ;
partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster;
partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); partition->fat.fatStart = startSector + u8array_to_u16( sectorBuffer, BPB_reservedSectors );
partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); partition->rootDirStart = partition->fat.fatStart + ( sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat );
partition->dataStart = partition->rootDirStart + partition->dataStart = partition->rootDirStart +
(( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); ( ( u8array_to_u16( sectorBuffer, BPB_rootEntries ) * DIR_ENTRY_DATA_SIZE ) / partition->bytesPerSector );
partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; partition->totalSize = ( ( uint64_t )partition->numberOfSectors - ( partition->dataStart - startSector ) ) * ( uint64_t )partition->bytesPerSector;
// Store info about FAT // Store info about FAT
uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; uint32_t clusterCount = ( partition->numberOfSectors - ( uint32_t )( partition->dataStart - startSector ) ) / partition->sectorsPerCluster;
partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1;
partition->fat.firstFree = CLUSTER_FIRST; partition->fat.firstFree = CLUSTER_FIRST;
if (clusterCount < CLUSTERS_PER_FAT12) { if ( clusterCount < CLUSTERS_PER_FAT12 )
partition->filesysType = FS_FAT12; // FAT12 volume {
} else if (clusterCount < CLUSTERS_PER_FAT16) { partition->filesysType = FS_FAT12; // FAT12 volume
partition->filesysType = FS_FAT16; // FAT16 volume }
} else { else if ( clusterCount < CLUSTERS_PER_FAT16 )
partition->filesysType = FS_FAT32; // FAT32 volume {
} partition->filesysType = FS_FAT16; // FAT16 volume
}
else
{
partition->filesysType = FS_FAT32; // FAT32 volume
}
if (partition->filesysType != FS_FAT32) { if ( partition->filesysType != FS_FAT32 )
partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; {
} else { partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER;
// Set up for the FAT32 way }
partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); else
// Check if FAT mirroring is enabled {
if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) { // Set up for the FAT32 way
// Use the active FAT partition->rootDirCluster = u8array_to_u32( sectorBuffer, BPB_FAT32_rootClus );
partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); // Check if FAT mirroring is enabled
} if ( !( sectorBuffer[BPB_FAT32_extFlags] & 0x80 ) )
} {
// Use the active FAT
partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * ( sectorBuffer[BPB_FAT32_extFlags] & 0x0F ) );
}
}
// Create a cache to use // Create a cache to use
partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors); partition->cache = _FAT_cache_constructor ( cacheSize, sectorsPerPage, partition->disc, startSector + partition->numberOfSectors );
// Set current directory to the root // Set current directory to the root
partition->cwdCluster = partition->rootDirCluster; partition->cwdCluster = partition->rootDirCluster;
// Check if this disc is writable, and set the readOnly property appropriately // Check if this disc is writable, and set the readOnly property appropriately
partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); partition->readOnly = !( _FAT_disc_features( disc ) & FEATURE_MEDIUM_CANWRITE );
// There are currently no open files on this partition // There are currently no open files on this partition
partition->openFileCount = 0; partition->openFileCount = 0;
partition->firstOpenFile = NULL; partition->firstOpenFile = NULL;
return partition; return partition;
} }
void _FAT_partition_destructor (PARTITION* partition) { void _FAT_partition_destructor ( PARTITION* partition )
FILE_STRUCT* nextFile; {
FILE_STRUCT* nextFile;
_FAT_lock(&partition->lock); _FAT_lock( &partition->lock );
// Synchronize open files // Synchronize open files
nextFile = partition->firstOpenFile; nextFile = partition->firstOpenFile;
while (nextFile) { while ( nextFile )
_FAT_syncToDisc (nextFile); {
nextFile = nextFile->nextOpenFile; _FAT_syncToDisc ( nextFile );
} nextFile = nextFile->nextOpenFile;
}
// Free memory used by the cache, writing it to disc at the same time // Free memory used by the cache, writing it to disc at the same time
_FAT_cache_destructor (partition->cache); _FAT_cache_destructor ( partition->cache );
// Unlock the partition and destroy the lock // Unlock the partition and destroy the lock
_FAT_unlock(&partition->lock); _FAT_unlock( &partition->lock );
_FAT_lock_deinit(&partition->lock); _FAT_lock_deinit( &partition->lock );
// Free memory used by the partition // Free memory used by the partition
_FAT_mem_free (partition); _FAT_mem_free ( partition );
} }
PARTITION* _FAT_partition_getPartitionFromPath (const char* path) { PARTITION* _FAT_partition_getPartitionFromPath ( const char* path )
const devoptab_t *devops; {
const devoptab_t *devops;
devops = GetDeviceOpTab (path); devops = GetDeviceOpTab ( path );
if (!devops) { if ( !devops )
return NULL; {
} return NULL;
}
return (PARTITION*)devops->deviceData; return ( PARTITION* )devops->deviceData;
} }

View File

@ -40,49 +40,51 @@ extern const char* DEVICE_NAME;
// Filesystem type // Filesystem type
typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE; typedef enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} FS_TYPE;
typedef struct { typedef struct
sec_t fatStart; {
uint32_t sectorsPerFat; sec_t fatStart;
uint32_t lastCluster; uint32_t sectorsPerFat;
uint32_t firstFree; uint32_t lastCluster;
uint32_t firstFree;
} FAT; } FAT;
typedef struct { typedef struct
const DISC_INTERFACE* disc; {
CACHE* cache; const DISC_INTERFACE* disc;
// Info about the partition CACHE* cache;
FS_TYPE filesysType; // Info about the partition
uint64_t totalSize; FS_TYPE filesysType;
sec_t rootDirStart; uint64_t totalSize;
uint32_t rootDirCluster; sec_t rootDirStart;
uint32_t numberOfSectors; uint32_t rootDirCluster;
sec_t dataStart; uint32_t numberOfSectors;
uint32_t bytesPerSector; sec_t dataStart;
uint32_t sectorsPerCluster; uint32_t bytesPerSector;
uint32_t bytesPerCluster; uint32_t sectorsPerCluster;
FAT fat; uint32_t bytesPerCluster;
// Values that may change after construction FAT fat;
uint32_t cwdCluster; // Current working directory cluster // Values that may change after construction
int openFileCount; uint32_t cwdCluster; // Current working directory cluster
struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files int openFileCount;
mutex_t lock; // A lock for partition operations struct _FILE_STRUCT* firstOpenFile; // The start of a linked list of files
bool readOnly; // If this is set, then do not try writing to the disc mutex_t lock; // A lock for partition operations
bool readOnly; // If this is set, then do not try writing to the disc
} PARTITION; } PARTITION;
/* /*
Mount the supplied device and return a pointer to the struct necessary to use it Mount the supplied device and return a pointer to the struct necessary to use it
*/ */
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector); PARTITION* _FAT_partition_constructor ( const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t SectorsPerPage, sec_t startSector );
/* /*
Dismount the device and free all structures used. Dismount the device and free all structures used.
Will also attempt to synchronise all open files to disc. Will also attempt to synchronise all open files to disc.
*/ */
void _FAT_partition_destructor (PARTITION* partition); void _FAT_partition_destructor ( PARTITION* partition );
/* /*
Return the partition specified in a path, as taken from the devoptab. Return the partition specified in a path, as taken from the devoptab.
*/ */
PARTITION* _FAT_partition_getPartitionFromPath (const char* path); PARTITION* _FAT_partition_getPartitionFromPath ( const char* path );
#endif // _PARTITION_H #endif // _PARTITION_H

File diff suppressed because it is too large Load Diff

View File

@ -25,30 +25,30 @@
#define ACLS_H #define ACLS_H
/* /*
* JPA configuration modes for security.c / acls.c * JPA configuration modes for security.c / acls.c
* should be moved to some config file * should be moved to some config file
*/ */
#define BUFSZ 1024 /* buffer size to read mapping file */ #define BUFSZ 1024 /* buffer size to read mapping file */
#define MAPPINGFILE ".NTFS-3G/UserMapping" /* default mapping file */ #define MAPPINGFILE ".NTFS-3G/UserMapping" /* default mapping file */
#define LINESZ 120 /* maximum useful size of a mapping line */ #define LINESZ 120 /* maximum useful size of a mapping line */
#define CACHE_PERMISSIONS_BITS 6 /* log2 of unitary allocation of permissions */ #define CACHE_PERMISSIONS_BITS 6 /* log2 of unitary allocation of permissions */
#define CACHE_PERMISSIONS_SIZE 262144 /* max cacheable permissions */ #define CACHE_PERMISSIONS_SIZE 262144 /* max cacheable permissions */
/* /*
* JPA The following must be in some library... * JPA The following must be in some library...
* but did not found out where * but did not found out where
*/ */
#define endian_rev16(x) (((x >> 8) & 255) | ((x & 255) << 8)) #define endian_rev16(x) (((x >> 8) & 255) | ((x & 255) << 8))
#define endian_rev32(x) (((x >> 24) & 255) | ((x >> 8) & 0xff00) \ #define endian_rev32(x) (((x >> 24) & 255) | ((x >> 8) & 0xff00) \
| ((x & 0xff00) << 8) | ((x & 255) << 24)) | ((x & 0xff00) << 8) | ((x & 255) << 24))
#define cpu_to_be16(x) endian_rev16(cpu_to_le16(x)) #define cpu_to_be16(x) endian_rev16(cpu_to_le16(x))
#define cpu_to_be32(x) endian_rev32(cpu_to_le32(x)) #define cpu_to_be32(x) endian_rev32(cpu_to_le32(x))
/* /*
* Macro definitions needed to share code with secaudit * Macro definitions needed to share code with secaudit
*/ */
#define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf) #define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf)
@ -58,25 +58,25 @@
/* /*
* Matching of ntfs permissions to Linux permissions * Matching of ntfs permissions to Linux permissions
* these constants are adapted to endianness * these constants are adapted to endianness
* when setting, set them all * when setting, set them all
* when checking, check one is present * when checking, check one is present
*/ */
/* flags which are set to mean exec, write or read */ /* flags which are set to mean exec, write or read */
#define FILE_READ (FILE_READ_DATA) #define FILE_READ (FILE_READ_DATA)
#define FILE_WRITE (FILE_WRITE_DATA | FILE_APPEND_DATA \ #define FILE_WRITE (FILE_WRITE_DATA | FILE_APPEND_DATA \
| READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA) | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA)
#define FILE_EXEC (FILE_EXECUTE) #define FILE_EXEC (FILE_EXECUTE)
#define DIR_READ FILE_LIST_DIRECTORY #define DIR_READ FILE_LIST_DIRECTORY
#define DIR_WRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD \ #define DIR_WRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | FILE_DELETE_CHILD \
| READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA) | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA)
#define DIR_EXEC (FILE_TRAVERSE) #define DIR_EXEC (FILE_TRAVERSE)
/* flags tested for meaning exec, write or read */ /* flags tested for meaning exec, write or read */
/* tests for write allow for interpretation of a sticky bit */ /* tests for write allow for interpretation of a sticky bit */
#define FILE_GREAD (FILE_READ_DATA | GENERIC_READ) #define FILE_GREAD (FILE_READ_DATA | GENERIC_READ)
#define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE) #define FILE_GWRITE (FILE_WRITE_DATA | FILE_APPEND_DATA | GENERIC_WRITE)
@ -85,115 +85,116 @@
#define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE) #define DIR_GWRITE (FILE_ADD_FILE | FILE_ADD_SUBDIRECTORY | GENERIC_WRITE)
#define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE) #define DIR_GEXEC (FILE_TRAVERSE | GENERIC_EXECUTE)
/* standard owner (and administrator) rights */ /* standard owner (and administrator) rights */
#define OWNER_RIGHTS (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER \ #define OWNER_RIGHTS (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER \
| SYNCHRONIZE \ | SYNCHRONIZE \
| FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES \ | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES \
| FILE_READ_EA | FILE_WRITE_EA) | FILE_READ_EA | FILE_WRITE_EA)
/* standard world rights */ /* standard world rights */
#define WORLD_RIGHTS (READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA \ #define WORLD_RIGHTS (READ_CONTROL | FILE_READ_ATTRIBUTES | FILE_READ_EA \
| SYNCHRONIZE) | SYNCHRONIZE)
/* inheritance flags for files and directories */ /* inheritance flags for files and directories */
#define FILE_INHERITANCE NO_PROPAGATE_INHERIT_ACE #define FILE_INHERITANCE NO_PROPAGATE_INHERIT_ACE
#define DIR_INHERITANCE (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE) #define DIR_INHERITANCE (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE)
/* /*
* To identify NTFS ACL meaning Posix ACL granted to root * To identify NTFS ACL meaning Posix ACL granted to root
* we use rights always granted to anybody, so they have no impact * we use rights always granted to anybody, so they have no impact
* either on Windows or on Linux. * either on Windows or on Linux.
*/ */
#define ROOT_OWNER_UNMARK SYNCHRONIZE /* ACL granted to root as owner */ #define ROOT_OWNER_UNMARK SYNCHRONIZE /* ACL granted to root as owner */
#define ROOT_GROUP_UNMARK FILE_READ_EA /* ACL granted to root as group */ #define ROOT_GROUP_UNMARK FILE_READ_EA /* ACL granted to root as group */
/* /*
* A type large enough to hold any SID * A type large enough to hold any SID
*/ */
typedef char BIGSID[40]; typedef char BIGSID[40];
/* /*
* Struct to hold the input mapping file * Struct to hold the input mapping file
* (private to this module) * (private to this module)
*/ */
struct MAPLIST { struct MAPLIST
struct MAPLIST *next; {
char *uidstr; /* uid text from the same record */ struct MAPLIST *next;
char *gidstr; /* gid text from the same record */ char *uidstr; /* uid text from the same record */
char *sidstr; /* sid text from the same record */ char *gidstr; /* gid text from the same record */
char maptext[LINESZ + 1]; char *sidstr; /* sid text from the same record */
char maptext[LINESZ + 1];
}; };
typedef int (*FILEREADER)(void *fileid, char *buf, size_t size, off_t pos); typedef int ( *FILEREADER )( void *fileid, char *buf, size_t size, off_t pos );
/* /*
* Constants defined in acls.c * Constants defined in acls.c
*/ */
extern const SID *adminsid; extern const SID *adminsid;
extern const SID *worldsid; extern const SID *worldsid;
/* /*
* Functions defined in acls.c * Functions defined in acls.c
*/ */
BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz); BOOL ntfs_valid_descr( const char *securattr, unsigned int attrsz );
BOOL ntfs_valid_pattern(const SID *sid); BOOL ntfs_valid_pattern( const SID *sid );
BOOL ntfs_valid_sid(const SID *sid); BOOL ntfs_valid_sid( const SID *sid );
BOOL ntfs_same_sid(const SID *first, const SID *second); BOOL ntfs_same_sid( const SID *first, const SID *second );
BOOL ntfs_is_user_sid(const SID *usid); BOOL ntfs_is_user_sid( const SID *usid );
int ntfs_sid_size(const SID * sid); int ntfs_sid_size( const SID * sid );
unsigned int ntfs_attr_size(const char *attr); unsigned int ntfs_attr_size( const char *attr );
const SID *ntfs_find_usid(const struct MAPPING *usermapping, const SID *ntfs_find_usid( const struct MAPPING *usermapping,
uid_t uid, SID *pdefsid); uid_t uid, SID *pdefsid );
const SID *ntfs_find_gsid(const struct MAPPING *groupmapping, const SID *ntfs_find_gsid( const struct MAPPING *groupmapping,
gid_t gid, SID *pdefsid); gid_t gid, SID *pdefsid );
uid_t ntfs_find_user(const struct MAPPING *usermapping, const SID *usid); uid_t ntfs_find_user( const struct MAPPING *usermapping, const SID *usid );
gid_t ntfs_find_group(const struct MAPPING *groupmapping, const SID * gsid); gid_t ntfs_find_group( const struct MAPPING *groupmapping, const SID * gsid );
const SID *ntfs_acl_owner(const char *secattr); const SID *ntfs_acl_owner( const char *secattr );
#if POSIXACLS #if POSIXACLS
BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc); BOOL ntfs_valid_posix( const struct POSIX_SECURITY *pxdesc );
void ntfs_sort_posix(struct POSIX_SECURITY *pxdesc); void ntfs_sort_posix( struct POSIX_SECURITY *pxdesc );
int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, mode_t mode); int ntfs_merge_mode_posix( struct POSIX_SECURITY *pxdesc, mode_t mode );
struct POSIX_SECURITY *ntfs_build_inherited_posix( struct POSIX_SECURITY *ntfs_build_inherited_posix(
const struct POSIX_SECURITY *pxdesc, mode_t mode, const struct POSIX_SECURITY *pxdesc, mode_t mode,
mode_t umask, BOOL isdir); mode_t umask, BOOL isdir );
struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc, struct POSIX_SECURITY *ntfs_replace_acl( const struct POSIX_SECURITY *oldpxdesc,
const struct POSIX_ACL *newacl, int count, BOOL deflt); const struct POSIX_ACL *newacl, int count, BOOL deflt );
struct POSIX_SECURITY *ntfs_build_permissions_posix( struct POSIX_SECURITY *ntfs_build_permissions_posix(
struct MAPPING* const mapping[], struct MAPPING* const mapping[],
const char *securattr, const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir); const SID *usid, const SID *gsid, BOOL isdir );
struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first, struct POSIX_SECURITY *ntfs_merge_descr_posix( const struct POSIX_SECURITY *first,
const struct POSIX_SECURITY *second); const struct POSIX_SECURITY *second );
char *ntfs_build_descr_posix(struct MAPPING* const mapping[], char *ntfs_build_descr_posix( struct MAPPING* const mapping[],
struct POSIX_SECURITY *pxdesc, struct POSIX_SECURITY *pxdesc,
int isdir, const SID *usid, const SID *gsid); int isdir, const SID *usid, const SID *gsid );
#endif /* POSIXACLS */ #endif /* POSIXACLS */
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, int ntfs_inherit_acl( const ACL *oldacl, ACL *newacl,
const SID *usid, const SID *gsid, BOOL fordir); const SID *usid, const SID *gsid, BOOL fordir );
int ntfs_build_permissions(const char *securattr, int ntfs_build_permissions( const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir); const SID *usid, const SID *gsid, BOOL isdir );
char *ntfs_build_descr(mode_t mode, char *ntfs_build_descr( mode_t mode,
int isdir, const SID * usid, const SID * gsid); int isdir, const SID * usid, const SID * gsid );
struct MAPLIST *ntfs_read_mapping(FILEREADER reader, void *fileid); struct MAPLIST *ntfs_read_mapping( FILEREADER reader, void *fileid );
struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem); struct MAPPING *ntfs_do_user_mapping( struct MAPLIST *firstitem );
struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem); struct MAPPING *ntfs_do_group_mapping( struct MAPLIST *firstitem );
void ntfs_free_mapping(struct MAPPING *mapping[]); void ntfs_free_mapping( struct MAPPING *mapping[] );
#endif /* ACLS_H */ #endif /* ACLS_H */

File diff suppressed because it is too large Load Diff

View File

@ -49,19 +49,20 @@ extern ntfschar TXF_DATA[10];
* *
* TODO: Describe them. * TODO: Describe them.
*/ */
typedef enum { typedef enum
LCN_HOLE = -1, /* Keep this as highest value or die! */ {
LCN_RL_NOT_MAPPED = -2, LCN_HOLE = -1, /* Keep this as highest value or die! */
LCN_ENOENT = -3, LCN_RL_NOT_MAPPED = -2,
LCN_EINVAL = -4, LCN_ENOENT = -3,
LCN_EIO = -5, LCN_EINVAL = -4,
LCN_EIO = -5,
} ntfs_lcn_special_values; } ntfs_lcn_special_values;
/** /**
* struct ntfs_attr_search_ctx - search context used in attribute search functions * struct ntfs_attr_search_ctx - search context used in attribute search functions
* @mrec: buffer containing mft record to search * @mrec: buffer containing mft record to search
* @attr: attribute record in @mrec where to begin/continue search * @attr: attribute record in @mrec where to begin/continue search
* @is_first: if true lookup_attr() begins search with @attr, else after @attr * @is_first: if true lookup_attr() begins search with @attr, else after @attr
* *
* Structure must be initialized to zero before the first call to one of the * Structure must be initialized to zero before the first call to one of the
* attribute search functions. Initialize @mrec to point to the mft record to * attribute search functions. Initialize @mrec to point to the mft record to
@ -75,35 +76,36 @@ typedef enum {
* any modification of the search context, to automagically get the next * any modification of the search context, to automagically get the next
* matching attribute. * matching attribute.
*/ */
struct _ntfs_attr_search_ctx { struct _ntfs_attr_search_ctx
MFT_RECORD *mrec; {
ATTR_RECORD *attr; MFT_RECORD *mrec;
BOOL is_first; ATTR_RECORD *attr;
ntfs_inode *ntfs_ino; BOOL is_first;
ATTR_LIST_ENTRY *al_entry; ntfs_inode *ntfs_ino;
ntfs_inode *base_ntfs_ino; ATTR_LIST_ENTRY *al_entry;
MFT_RECORD *base_mrec; ntfs_inode *base_ntfs_ino;
ATTR_RECORD *base_attr; MFT_RECORD *base_mrec;
ATTR_RECORD *base_attr;
}; };
extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx); extern void ntfs_attr_reinit_search_ctx( ntfs_attr_search_ctx *ctx );
extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx( ntfs_inode *ni,
MFT_RECORD *mrec); MFT_RECORD *mrec );
extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx); extern void ntfs_attr_put_search_ctx( ntfs_attr_search_ctx *ctx );
extern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name, extern int ntfs_attr_lookup( const ATTR_TYPES type, const ntfschar *name,
const u32 name_len, const IGNORE_CASE_BOOL ic, const u32 name_len, const IGNORE_CASE_BOOL ic,
const VCN lowest_vcn, const u8 *val, const u32 val_len, const VCN lowest_vcn, const u8 *val, const u32 val_len,
ntfs_attr_search_ctx *ctx); ntfs_attr_search_ctx *ctx );
extern int ntfs_attr_position(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx); extern int ntfs_attr_position( const ATTR_TYPES type, ntfs_attr_search_ctx *ctx );
extern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol, extern ATTR_DEF *ntfs_attr_find_in_attrdef( const ntfs_volume *vol,
const ATTR_TYPES type); const ATTR_TYPES type );
/** /**
* ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
* @ctx: initialised attribute search context * @ctx: initialised attribute search context
* *
* Syntactic sugar for walking attributes in an inode. * Syntactic sugar for walking attributes in an inode.
* *
@ -111,42 +113,42 @@ extern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
* ntfs_attr_lookup(). * ntfs_attr_lookup().
* *
* Example: When you want to enumerate all attributes in an open ntfs inode * Example: When you want to enumerate all attributes in an open ntfs inode
* @ni, you can simply do: * @ni, you can simply do:
* *
* int err; * int err;
* ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL); * ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL);
* if (!ctx) * if (!ctx)
* // Error code is in errno. Handle this case. * // Error code is in errno. Handle this case.
* while (!(err = ntfs_attrs_walk(ctx))) { * while (!(err = ntfs_attrs_walk(ctx))) {
* ATTR_RECORD *attr = ctx->attr; * ATTR_RECORD *attr = ctx->attr;
* // attr now contains the next attribute. Do whatever you want * // attr now contains the next attribute. Do whatever you want
* // with it and then just continue with the while loop. * // with it and then just continue with the while loop.
* } * }
* if (err && errno != ENOENT) * if (err && errno != ENOENT)
* // Ooops. An error occurred! You should handle this case. * // Ooops. An error occurred! You should handle this case.
* // Now finished with all attributes in the inode. * // Now finished with all attributes in the inode.
*/ */
static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx) static __inline__ int ntfs_attrs_walk( ntfs_attr_search_ctx *ctx )
{ {
return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0, return ntfs_attr_lookup( AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
NULL, 0, ctx); NULL, 0, ctx );
} }
/** /**
* struct ntfs_attr - ntfs in memory non-resident attribute structure * struct ntfs_attr - ntfs in memory non-resident attribute structure
* @rl: if not NULL, the decompressed runlist * @rl: if not NULL, the decompressed runlist
* @ni: base ntfs inode to which this attribute belongs * @ni: base ntfs inode to which this attribute belongs
* @type: attribute type * @type: attribute type
* @name: Unicode name of the attribute * @name: Unicode name of the attribute
* @name_len: length of @name in Unicode characters * @name_len: length of @name in Unicode characters
* @state: NTFS attribute specific flags describing this attribute * @state: NTFS attribute specific flags describing this attribute
* @allocated_size: copy from the attribute record * @allocated_size: copy from the attribute record
* @data_size: copy from the attribute record * @data_size: copy from the attribute record
* @initialized_size: copy from the attribute record * @initialized_size: copy from the attribute record
* @compressed_size: copy from the attribute record * @compressed_size: copy from the attribute record
* @compression_block_size: size of a compression block (cb) * @compression_block_size: size of a compression block (cb)
* @compression_block_size_bits: log2 of the size of a cb * @compression_block_size_bits: log2 of the size of a cb
* @compression_block_clusters: number of clusters per cb * @compression_block_clusters: number of clusters per cb
* *
* This structure exists purely to provide a mechanism of caching the runlist * This structure exists purely to provide a mechanism of caching the runlist
* of an attribute. If you want to operate on a particular attribute extent, * of an attribute. If you want to operate on a particular attribute extent,
@ -174,68 +176,70 @@ static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx)
* @state contains NTFS attribute specific flags describing this attribute * @state contains NTFS attribute specific flags describing this attribute
* structure. See ntfs_attr_state_bits above. * structure. See ntfs_attr_state_bits above.
*/ */
struct _ntfs_attr { struct _ntfs_attr
runlist_element *rl; {
ntfs_inode *ni; runlist_element *rl;
ATTR_TYPES type; ntfs_inode *ni;
ATTR_FLAGS data_flags; ATTR_TYPES type;
ntfschar *name; ATTR_FLAGS data_flags;
u32 name_len; ntfschar *name;
unsigned long state; u32 name_len;
s64 allocated_size; unsigned long state;
s64 data_size; s64 allocated_size;
s64 initialized_size; s64 data_size;
s64 compressed_size; s64 initialized_size;
u32 compression_block_size; s64 compressed_size;
u8 compression_block_size_bits; u32 compression_block_size;
u8 compression_block_clusters; u8 compression_block_size_bits;
s8 unused_runs; /* pre-reserved entries available */ u8 compression_block_clusters;
s8 unused_runs; /* pre-reserved entries available */
}; };
/** /**
* enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr * enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr
* structure * structure
*/ */
typedef enum { typedef enum
NA_Initialized, /* 1: structure is initialized. */ {
NA_NonResident, /* 1: Attribute is not resident. */ NA_Initialized, /* 1: structure is initialized. */
NA_BeingNonResident, /* 1: Attribute is being made not resident. */ NA_NonResident, /* 1: Attribute is not resident. */
NA_FullyMapped, /* 1: Attribute has been fully mapped */ NA_BeingNonResident, /* 1: Attribute is being made not resident. */
NA_ComprClosing, /* 1: Compressed attribute is being closed */ NA_FullyMapped, /* 1: Attribute has been fully mapped */
NA_ComprClosing, /* 1: Compressed attribute is being closed */
} ntfs_attr_state_bits; } ntfs_attr_state_bits;
#define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state) #define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state)
#define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state) #define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state)
#define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state) #define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state)
#define NAttrInitialized(na) test_nattr_flag(na, Initialized) #define NAttrInitialized(na) test_nattr_flag(na, Initialized)
#define NAttrSetInitialized(na) set_nattr_flag(na, Initialized) #define NAttrSetInitialized(na) set_nattr_flag(na, Initialized)
#define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized) #define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized)
#define NAttrNonResident(na) test_nattr_flag(na, NonResident) #define NAttrNonResident(na) test_nattr_flag(na, NonResident)
#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident) #define NAttrSetNonResident(na) set_nattr_flag(na, NonResident)
#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident) #define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident)
#define NAttrBeingNonResident(na) test_nattr_flag(na, BeingNonResident) #define NAttrBeingNonResident(na) test_nattr_flag(na, BeingNonResident)
#define NAttrSetBeingNonResident(na) set_nattr_flag(na, BeingNonResident) #define NAttrSetBeingNonResident(na) set_nattr_flag(na, BeingNonResident)
#define NAttrClearBeingNonResident(na) clear_nattr_flag(na, BeingNonResident) #define NAttrClearBeingNonResident(na) clear_nattr_flag(na, BeingNonResident)
#define NAttrFullyMapped(na) test_nattr_flag(na, FullyMapped) #define NAttrFullyMapped(na) test_nattr_flag(na, FullyMapped)
#define NAttrSetFullyMapped(na) set_nattr_flag(na, FullyMapped) #define NAttrSetFullyMapped(na) set_nattr_flag(na, FullyMapped)
#define NAttrClearFullyMapped(na) clear_nattr_flag(na, FullyMapped) #define NAttrClearFullyMapped(na) clear_nattr_flag(na, FullyMapped)
#define NAttrComprClosing(na) test_nattr_flag(na, ComprClosing) #define NAttrComprClosing(na) test_nattr_flag(na, ComprClosing)
#define NAttrSetComprClosing(na) set_nattr_flag(na, ComprClosing) #define NAttrSetComprClosing(na) set_nattr_flag(na, ComprClosing)
#define NAttrClearComprClosing(na) clear_nattr_flag(na, ComprClosing) #define NAttrClearComprClosing(na) clear_nattr_flag(na, ComprClosing)
#define GenNAttrIno(func_name, flag) \ #define GenNAttrIno(func_name, flag) \
extern int NAttr##func_name(ntfs_attr *na); \ extern int NAttr##func_name(ntfs_attr *na); \
extern void NAttrSet##func_name(ntfs_attr *na); \ extern void NAttrSet##func_name(ntfs_attr *na); \
extern void NAttrClear##func_name(ntfs_attr *na); extern void NAttrClear##func_name(ntfs_attr *na);
GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED) GenNAttrIno( Compressed, FILE_ATTR_COMPRESSED )
GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED) GenNAttrIno( Encrypted, FILE_ATTR_ENCRYPTED )
GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE) GenNAttrIno( Sparse, FILE_ATTR_SPARSE_FILE )
#undef GenNAttrIno #undef GenNAttrIno
/** /**
@ -243,99 +247,100 @@ GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE)
* *
* For convenience. Used in the attr structure. * For convenience. Used in the attr structure.
*/ */
typedef union { typedef union
u8 _default; /* Unnamed u8 to serve as default when just using {
a_val without specifying any of the below. */ u8 _default; /* Unnamed u8 to serve as default when just using
STANDARD_INFORMATION std_inf; a_val without specifying any of the below. */
ATTR_LIST_ENTRY al_entry; STANDARD_INFORMATION std_inf;
FILE_NAME_ATTR filename; ATTR_LIST_ENTRY al_entry;
OBJECT_ID_ATTR obj_id; FILE_NAME_ATTR filename;
SECURITY_DESCRIPTOR_ATTR sec_desc; OBJECT_ID_ATTR obj_id;
VOLUME_NAME vol_name; SECURITY_DESCRIPTOR_ATTR sec_desc;
VOLUME_INFORMATION vol_inf; VOLUME_NAME vol_name;
DATA_ATTR data; VOLUME_INFORMATION vol_inf;
INDEX_ROOT index_root; DATA_ATTR data;
INDEX_BLOCK index_blk; INDEX_ROOT index_root;
BITMAP_ATTR bmp; INDEX_BLOCK index_blk;
REPARSE_POINT reparse; BITMAP_ATTR bmp;
EA_INFORMATION ea_inf; REPARSE_POINT reparse;
EA_ATTR ea; EA_INFORMATION ea_inf;
PROPERTY_SET property_set; EA_ATTR ea;
LOGGED_UTILITY_STREAM logged_util_stream; PROPERTY_SET property_set;
EFS_ATTR_HEADER efs; LOGGED_UTILITY_STREAM logged_util_stream;
EFS_ATTR_HEADER efs;
} attr_val; } attr_val;
extern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, extern void ntfs_attr_init( ntfs_attr *na, const BOOL non_resident,
const ATTR_FLAGS data_flags, const BOOL encrypted, const ATTR_FLAGS data_flags, const BOOL encrypted,
const BOOL sparse, const BOOL sparse,
const s64 allocated_size, const s64 data_size, const s64 allocated_size, const s64 data_size,
const s64 initialized_size, const s64 compressed_size, const s64 initialized_size, const s64 compressed_size,
const u8 compression_unit); const u8 compression_unit );
/* warning : in the following "name" has to be freeable */ /* warning : in the following "name" has to be freeable */
/* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */ /* or one of constants AT_UNNAMED, NTFS_INDEX_I30 or STREAM_SDS */
extern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, extern ntfs_attr *ntfs_attr_open( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len); ntfschar *name, u32 name_len );
extern void ntfs_attr_close(ntfs_attr *na); extern void ntfs_attr_close( ntfs_attr *na );
extern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, extern s64 ntfs_attr_pread( ntfs_attr *na, const s64 pos, s64 count,
void *b); void *b );
extern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, extern s64 ntfs_attr_pwrite( ntfs_attr *na, const s64 pos, s64 count,
const void *b); const void *b );
extern int ntfs_attr_pclose(ntfs_attr *na); extern int ntfs_attr_pclose( ntfs_attr *na );
extern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, extern void *ntfs_attr_readall( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len, s64 *data_size); ntfschar *name, u32 name_len, s64 *data_size );
extern s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, extern s64 ntfs_attr_mst_pread( ntfs_attr *na, const s64 pos,
const s64 bk_cnt, const u32 bk_size, void *dst); const s64 bk_cnt, const u32 bk_size, void *dst );
extern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, extern s64 ntfs_attr_mst_pwrite( ntfs_attr *na, const s64 pos,
s64 bk_cnt, const u32 bk_size, void *src); s64 bk_cnt, const u32 bk_size, void *src );
extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn); extern int ntfs_attr_map_runlist( ntfs_attr *na, VCN vcn );
extern int ntfs_attr_map_whole_runlist(ntfs_attr *na); extern int ntfs_attr_map_whole_runlist( ntfs_attr *na );
extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn); extern LCN ntfs_attr_vcn_to_lcn( ntfs_attr *na, const VCN vcn );
extern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn); extern runlist_element *ntfs_attr_find_vcn( ntfs_attr *na, const VCN vcn );
extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol, extern int ntfs_attr_size_bounds_check( const ntfs_volume *vol,
const ATTR_TYPES type, const s64 size); const ATTR_TYPES type, const s64 size );
extern int ntfs_attr_can_be_resident(const ntfs_volume *vol, extern int ntfs_attr_can_be_resident( const ntfs_volume *vol,
const ATTR_TYPES type); const ATTR_TYPES type );
int ntfs_attr_make_non_resident(ntfs_attr *na, int ntfs_attr_make_non_resident( ntfs_attr *na,
ntfs_attr_search_ctx *ctx); ntfs_attr_search_ctx *ctx );
int ntfs_attr_force_non_resident(ntfs_attr *na); int ntfs_attr_force_non_resident( ntfs_attr *na );
extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size); extern int ntfs_make_room_for_attr( MFT_RECORD *m, u8 *pos, u32 size );
extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, extern int ntfs_resident_attr_record_add( ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, u8 *val, u32 size, ntfschar *name, u8 name_len, u8 *val, u32 size,
ATTR_FLAGS flags); ATTR_FLAGS flags );
extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, extern int ntfs_non_resident_attr_record_add( ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
ATTR_FLAGS flags); ATTR_FLAGS flags );
extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx); extern int ntfs_attr_record_rm( ntfs_attr_search_ctx *ctx );
extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, extern int ntfs_attr_add( ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, u8 *val, s64 size); ntfschar *name, u8 name_len, u8 *val, s64 size );
extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, extern int ntfs_attr_set_flags( ntfs_inode *ni, ATTR_TYPES type,
ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask); ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask );
extern int ntfs_attr_rm(ntfs_attr *na); extern int ntfs_attr_rm( ntfs_attr *na );
extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size); extern int ntfs_attr_record_resize( MFT_RECORD *m, ATTR_RECORD *a, u32 new_size );
extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, extern int ntfs_resident_attr_value_resize( MFT_RECORD *m, ATTR_RECORD *a,
const u32 new_size); const u32 new_size );
extern int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni); extern int ntfs_attr_record_move_to( ntfs_attr_search_ctx *ctx, ntfs_inode *ni );
extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra); extern int ntfs_attr_record_move_away( ntfs_attr_search_ctx *ctx, int extra );
extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn); extern int ntfs_attr_update_mapping_pairs( ntfs_attr *na, VCN from_vcn );
extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize); extern int ntfs_attr_truncate( ntfs_attr *na, const s64 newsize );
/** /**
* get_attribute_value_length - return the length of the value of an attribute * get_attribute_value_length - return the length of the value of an attribute
* @a: pointer to a buffer containing the attribute record * @a: pointer to a buffer containing the attribute record
* *
* Return the byte size of the attribute value of the attribute @a (as it * Return the byte size of the attribute value of the attribute @a (as it
* would be after eventual decompression and filling in of holes if sparse). * would be after eventual decompression and filling in of holes if sparse).
@ -344,13 +349,13 @@ extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize);
* *
* FIXME: Describe possible errnos. * FIXME: Describe possible errnos.
*/ */
extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a); extern s64 ntfs_get_attribute_value_length( const ATTR_RECORD *a );
/** /**
* get_attribute_value - return the attribute value of an attribute * get_attribute_value - return the attribute value of an attribute
* @vol: volume on which the attribute is present * @vol: volume on which the attribute is present
* @a: attribute to get the value of * @a: attribute to get the value of
* @b: destination buffer for the attribute value * @b: destination buffer for the attribute value
* *
* Make a copy of the attribute value of the attribute @a into the destination * Make a copy of the attribute value of the attribute @a into the destination
* buffer @b. Note, that the size of @b has to be at least equal to the value * buffer @b. Note, that the size of @b has to be at least equal to the value
@ -360,16 +365,16 @@ extern s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
* then nothing was read due to a zero-length attribute value, otherwise * then nothing was read due to a zero-length attribute value, otherwise
* errno describes the error. * errno describes the error.
*/ */
extern s64 ntfs_get_attribute_value(const ntfs_volume *vol, extern s64 ntfs_get_attribute_value( const ntfs_volume *vol,
const ATTR_RECORD *a, u8 *b); const ATTR_RECORD *a, u8 *b );
extern void ntfs_attr_name_free(char **name); extern void ntfs_attr_name_free( char **name );
extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len); extern char *ntfs_attr_name_get( const ntfschar *uname, const int uname_len );
extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, extern int ntfs_attr_exist( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len); ntfschar *name, u32 name_len );
extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, extern int ntfs_attr_remove( ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len); ntfschar *name, u32 name_len );
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na); extern s64 ntfs_attr_get_free_bits( ntfs_attr *na );
#endif /* defined _NTFS_ATTRIB_H */ #endif /* defined _NTFS_ATTRIB_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/** /**
* attrlist.c - Attribute list attribute handling code. Originated from the Linux-NTFS * attrlist.c - Attribute list attribute handling code. Originated from the Linux-NTFS
* project. * project.
* *
* Copyright (c) 2004-2005 Anton Altaparmakov * Copyright (c) 2004-2005 Anton Altaparmakov
* Copyright (c) 2004-2005 Yura Pakhuchiy * Copyright (c) 2004-2005 Yura Pakhuchiy
@ -47,7 +47,7 @@
/** /**
* ntfs_attrlist_need - check whether inode need attribute list * ntfs_attrlist_need - check whether inode need attribute list
* @ni: opened ntfs inode for which perform check * @ni: opened ntfs inode for which perform check
* *
* Check whether all are attributes belong to one MFT record, in that case * Check whether all are attributes belong to one MFT record, in that case
* attribute list is not needed. * attribute list is not needed.
@ -55,260 +55,278 @@
* Return 1 if inode need attribute list, 0 if not, -1 on error with errno set * Return 1 if inode need attribute list, 0 if not, -1 on error with errno set
* to the error code. If function succeed errno set to 0. The following error * to the error code. If function succeed errno set to 0. The following error
* codes are defined: * codes are defined:
* EINVAL - Invalid arguments passed to function or attribute haven't got * EINVAL - Invalid arguments passed to function or attribute haven't got
* attribute list. * attribute list.
*/ */
int ntfs_attrlist_need(ntfs_inode *ni) int ntfs_attrlist_need( ntfs_inode *ni )
{ {
ATTR_LIST_ENTRY *ale; ATTR_LIST_ENTRY *ale;
if (!ni) { if ( !ni )
ntfs_log_trace("Invalid arguments.\n"); {
errno = EINVAL; ntfs_log_trace( "Invalid arguments.\n" );
return -1; errno = EINVAL;
} return -1;
}
ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); ntfs_log_trace( "Entering for inode 0x%llx.\n", ( long long ) ni->mft_no );
if (!NInoAttrList(ni)) { if ( !NInoAttrList( ni ) )
ntfs_log_trace("Inode haven't got attribute list.\n"); {
errno = EINVAL; ntfs_log_trace( "Inode haven't got attribute list.\n" );
return -1; errno = EINVAL;
} return -1;
}
if (!ni->attr_list) { if ( !ni->attr_list )
ntfs_log_trace("Corrupt in-memory struct.\n"); {
errno = EINVAL; ntfs_log_trace( "Corrupt in-memory struct.\n" );
return -1; errno = EINVAL;
} return -1;
}
errno = 0; errno = 0;
ale = (ATTR_LIST_ENTRY *)ni->attr_list; ale = ( ATTR_LIST_ENTRY * )ni->attr_list;
while ((u8*)ale < ni->attr_list + ni->attr_list_size) { while ( ( u8* )ale < ni->attr_list + ni->attr_list_size )
if (MREF_LE(ale->mft_reference) != ni->mft_no) {
return 1; if ( MREF_LE( ale->mft_reference ) != ni->mft_no )
ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length)); return 1;
} ale = ( ATTR_LIST_ENTRY * )( ( u8* )ale + le16_to_cpu( ale->length ) );
return 0; }
return 0;
} }
/** /**
* ntfs_attrlist_entry_add - add an attribute list attribute entry * ntfs_attrlist_entry_add - add an attribute list attribute entry
* @ni: opened ntfs inode, which contains that attribute * @ni: opened ntfs inode, which contains that attribute
* @attr: attribute record to add to attribute list * @attr: attribute record to add to attribute list
* *
* Return 0 on success and -1 on error with errno set to the error code. The * Return 0 on success and -1 on error with errno set to the error code. The
* following error codes are defined: * following error codes are defined:
* EINVAL - Invalid arguments passed to function. * EINVAL - Invalid arguments passed to function.
* ENOMEM - Not enough memory to allocate necessary buffers. * ENOMEM - Not enough memory to allocate necessary buffers.
* EIO - I/O error occurred or damaged filesystem. * EIO - I/O error occurred or damaged filesystem.
* EEXIST - Such attribute already present in attribute list. * EEXIST - Such attribute already present in attribute list.
*/ */
int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr) int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr )
{ {
ATTR_LIST_ENTRY *ale; ATTR_LIST_ENTRY *ale;
MFT_REF mref; MFT_REF mref;
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
u8 *new_al; u8 *new_al;
int entry_len, entry_offset, err; int entry_len, entry_offset, err;
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", ntfs_log_trace( "Entering for inode 0x%llx, attr 0x%x.\n",
(long long) ni->mft_no, ( long long ) ni->mft_no,
(unsigned) le32_to_cpu(attr->type)); ( unsigned ) le32_to_cpu( attr->type ) );
if (!ni || !attr) { if ( !ni || !attr )
ntfs_log_trace("Invalid arguments.\n"); {
errno = EINVAL; ntfs_log_trace( "Invalid arguments.\n" );
return -1; errno = EINVAL;
} return -1;
}
mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)); mref = MK_LE_MREF( ni->mft_no, le16_to_cpu( ni->mrec->sequence_number ) );
if (ni->nr_extents == -1) if ( ni->nr_extents == -1 )
ni = ni->base_ni; ni = ni->base_ni;
if (!NInoAttrList(ni)) { if ( !NInoAttrList( ni ) )
ntfs_log_trace("Attribute list isn't present.\n"); {
errno = ENOENT; ntfs_log_trace( "Attribute list isn't present.\n" );
return -1; errno = ENOENT;
} return -1;
}
/* Determine size and allocate memory for new attribute list. */ /* Determine size and allocate memory for new attribute list. */
entry_len = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * entry_len = ( sizeof( ATTR_LIST_ENTRY ) + sizeof( ntfschar ) *
attr->name_length + 7) & ~7; attr->name_length + 7 ) & ~7;
new_al = ntfs_calloc(ni->attr_list_size + entry_len); new_al = ntfs_calloc( ni->attr_list_size + entry_len );
if (!new_al) if ( !new_al )
return -1; return -1;
/* Find place for the new entry. */ /* Find place for the new entry. */
ctx = ntfs_attr_get_search_ctx(ni, NULL); ctx = ntfs_attr_get_search_ctx( ni, NULL );
if (!ctx) { if ( !ctx )
err = errno; {
goto err_out; err = errno;
} goto err_out;
if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*) }
((u8*)attr + le16_to_cpu(attr->name_offset)) : if ( !ntfs_attr_lookup( attr->type, ( attr->name_length ) ? ( ntfschar* )
AT_UNNAMED, attr->name_length, CASE_SENSITIVE, ( ( u8* )attr + le16_to_cpu( attr->name_offset ) ) :
(attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) : AT_UNNAMED, attr->name_length, CASE_SENSITIVE,
0, (attr->non_resident) ? NULL : ((u8*)attr + ( attr->non_resident ) ? le64_to_cpu( attr->lowest_vcn ) :
le16_to_cpu(attr->value_offset)), (attr->non_resident) ? 0, ( attr->non_resident ) ? NULL : ( ( u8* )attr +
0 : le32_to_cpu(attr->value_length), ctx)) { le16_to_cpu( attr->value_offset ) ), ( attr->non_resident ) ?
/* Found some extent, check it to be before new extent. */ 0 : le32_to_cpu( attr->value_length ), ctx ) )
if (ctx->al_entry->lowest_vcn == attr->lowest_vcn) { {
err = EEXIST; /* Found some extent, check it to be before new extent. */
ntfs_log_trace("Such attribute already present in the " if ( ctx->al_entry->lowest_vcn == attr->lowest_vcn )
"attribute list.\n"); {
ntfs_attr_put_search_ctx(ctx); err = EEXIST;
goto err_out; ntfs_log_trace( "Such attribute already present in the "
} "attribute list.\n" );
/* Add new entry after this extent. */ ntfs_attr_put_search_ctx( ctx );
ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry + goto err_out;
le16_to_cpu(ctx->al_entry->length)); }
} else { /* Add new entry after this extent. */
/* Check for real errors. */ ale = ( ATTR_LIST_ENTRY* )( ( u8* )ctx->al_entry +
if (errno != ENOENT) { le16_to_cpu( ctx->al_entry->length ) );
err = errno; }
ntfs_log_trace("Attribute lookup failed.\n"); else
ntfs_attr_put_search_ctx(ctx); {
goto err_out; /* Check for real errors. */
} if ( errno != ENOENT )
/* No previous extents found. */ {
ale = ctx->al_entry; err = errno;
} ntfs_log_trace( "Attribute lookup failed.\n" );
/* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */ ntfs_attr_put_search_ctx( ctx );
ntfs_attr_put_search_ctx(ctx); goto err_out;
}
/* No previous extents found. */
ale = ctx->al_entry;
}
/* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */
ntfs_attr_put_search_ctx( ctx );
/* Determine new entry offset. */ /* Determine new entry offset. */
entry_offset = ((u8 *)ale - ni->attr_list); entry_offset = ( ( u8 * )ale - ni->attr_list );
/* Set pointer to new entry. */ /* Set pointer to new entry. */
ale = (ATTR_LIST_ENTRY *)(new_al + entry_offset); ale = ( ATTR_LIST_ENTRY * )( new_al + entry_offset );
/* Zero it to fix valgrind warning. */ /* Zero it to fix valgrind warning. */
memset(ale, 0, entry_len); memset( ale, 0, entry_len );
/* Form new entry. */ /* Form new entry. */
ale->type = attr->type; ale->type = attr->type;
ale->length = cpu_to_le16(entry_len); ale->length = cpu_to_le16( entry_len );
ale->name_length = attr->name_length; ale->name_length = attr->name_length;
ale->name_offset = offsetof(ATTR_LIST_ENTRY, name); ale->name_offset = offsetof( ATTR_LIST_ENTRY, name );
if (attr->non_resident) if ( attr->non_resident )
ale->lowest_vcn = attr->lowest_vcn; ale->lowest_vcn = attr->lowest_vcn;
else else
ale->lowest_vcn = 0; ale->lowest_vcn = 0;
ale->mft_reference = mref; ale->mft_reference = mref;
ale->instance = attr->instance; ale->instance = attr->instance;
memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset), memcpy( ale->name, ( u8 * )attr + le16_to_cpu( attr->name_offset ),
attr->name_length * sizeof(ntfschar)); attr->name_length * sizeof( ntfschar ) );
/* Resize $ATTRIBUTE_LIST to new length. */ /* Resize $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); na = ntfs_attr_open( ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0 );
if (!na) { if ( !na )
err = errno; {
ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); err = errno;
goto err_out; ntfs_log_trace( "Failed to open $ATTRIBUTE_LIST attribute.\n" );
} goto err_out;
if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) { }
err = errno; if ( ntfs_attr_truncate( na, ni->attr_list_size + entry_len ) )
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); {
goto err_out; err = errno;
} ntfs_log_trace( "$ATTRIBUTE_LIST resize failed.\n" );
goto err_out;
}
/* Copy entries from old attribute list to new. */ /* Copy entries from old attribute list to new. */
memcpy(new_al, ni->attr_list, entry_offset); memcpy( new_al, ni->attr_list, entry_offset );
memcpy(new_al + entry_offset + entry_len, ni->attr_list + memcpy( new_al + entry_offset + entry_len, ni->attr_list +
entry_offset, ni->attr_list_size - entry_offset); entry_offset, ni->attr_list_size - entry_offset );
/* Set new runlist. */ /* Set new runlist. */
free(ni->attr_list); free( ni->attr_list );
ni->attr_list = new_al; ni->attr_list = new_al;
ni->attr_list_size = ni->attr_list_size + entry_len; ni->attr_list_size = ni->attr_list_size + entry_len;
NInoAttrListSetDirty(ni); NInoAttrListSetDirty( ni );
/* Done! */ /* Done! */
ntfs_attr_close(na); ntfs_attr_close( na );
return 0; return 0;
err_out: err_out:
if (na) if ( na )
ntfs_attr_close(na); ntfs_attr_close( na );
free(new_al); free( new_al );
errno = err; errno = err;
return -1; return -1;
} }
/** /**
* ntfs_attrlist_entry_rm - remove an attribute list attribute entry * ntfs_attrlist_entry_rm - remove an attribute list attribute entry
* @ctx: attribute search context describing the attribute list entry * @ctx: attribute search context describing the attribute list entry
* *
* Remove the attribute list entry @ctx->al_entry from the attribute list. * Remove the attribute list entry @ctx->al_entry from the attribute list.
* *
* Return 0 on success and -1 on error with errno set to the error code. * Return 0 on success and -1 on error with errno set to the error code.
*/ */
int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx) int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx )
{ {
u8 *new_al; u8 *new_al;
int new_al_len; int new_al_len;
ntfs_inode *base_ni; ntfs_inode *base_ni;
ntfs_attr *na; ntfs_attr *na;
ATTR_LIST_ENTRY *ale; ATTR_LIST_ENTRY *ale;
int err; int err;
if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) { if ( !ctx || !ctx->ntfs_ino || !ctx->al_entry )
ntfs_log_trace("Invalid arguments.\n"); {
errno = EINVAL; ntfs_log_trace( "Invalid arguments.\n" );
return -1; errno = EINVAL;
} return -1;
}
if (ctx->base_ntfs_ino) if ( ctx->base_ntfs_ino )
base_ni = ctx->base_ntfs_ino; base_ni = ctx->base_ntfs_ino;
else else
base_ni = ctx->ntfs_ino; base_ni = ctx->ntfs_ino;
ale = ctx->al_entry; ale = ctx->al_entry;
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n", ntfs_log_trace( "Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n",
(long long) ctx->ntfs_ino->mft_no, ( long long ) ctx->ntfs_ino->mft_no,
(unsigned) le32_to_cpu(ctx->al_entry->type), ( unsigned ) le32_to_cpu( ctx->al_entry->type ),
(long long) le64_to_cpu(ctx->al_entry->lowest_vcn)); ( long long ) le64_to_cpu( ctx->al_entry->lowest_vcn ) );
if (!NInoAttrList(base_ni)) { if ( !NInoAttrList( base_ni ) )
ntfs_log_trace("Attribute list isn't present.\n"); {
errno = ENOENT; ntfs_log_trace( "Attribute list isn't present.\n" );
return -1; errno = ENOENT;
} return -1;
}
/* Allocate memory for new attribute list. */ /* Allocate memory for new attribute list. */
new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length); new_al_len = base_ni->attr_list_size - le16_to_cpu( ale->length );
new_al = ntfs_calloc(new_al_len); new_al = ntfs_calloc( new_al_len );
if (!new_al) if ( !new_al )
return -1; return -1;
/* Reisze $ATTRIBUTE_LIST to new length. */ /* Reisze $ATTRIBUTE_LIST to new length. */
na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); na = ntfs_attr_open( base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0 );
if (!na) { if ( !na )
err = errno; {
ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); err = errno;
goto err_out; ntfs_log_trace( "Failed to open $ATTRIBUTE_LIST attribute.\n" );
} goto err_out;
if (ntfs_attr_truncate(na, new_al_len)) { }
err = errno; if ( ntfs_attr_truncate( na, new_al_len ) )
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); {
goto err_out; err = errno;
} ntfs_log_trace( "$ATTRIBUTE_LIST resize failed.\n" );
goto err_out;
}
/* Copy entries from old attribute list to new. */ /* Copy entries from old attribute list to new. */
memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list); memcpy( new_al, base_ni->attr_list, ( u8* )ale - base_ni->attr_list );
memcpy(new_al + ((u8*)ale - base_ni->attr_list), (u8*)ale + le16_to_cpu( memcpy( new_al + ( ( u8* )ale - base_ni->attr_list ), ( u8* )ale + le16_to_cpu(
ale->length), new_al_len - ((u8*)ale - base_ni->attr_list)); ale->length ), new_al_len - ( ( u8* )ale - base_ni->attr_list ) );
/* Set new runlist. */ /* Set new runlist. */
free(base_ni->attr_list); free( base_ni->attr_list );
base_ni->attr_list = new_al; base_ni->attr_list = new_al;
base_ni->attr_list_size = new_al_len; base_ni->attr_list_size = new_al_len;
NInoAttrListSetDirty(base_ni); NInoAttrListSetDirty( base_ni );
/* Done! */ /* Done! */
ntfs_attr_close(na); ntfs_attr_close( na );
return 0; return 0;
err_out: err_out:
if (na) if ( na )
ntfs_attr_close(na); ntfs_attr_close( na );
free(new_al); free( new_al );
errno = err; errno = err;
return -1; return -1;
} }

View File

@ -1,6 +1,6 @@
/* /*
* attrlist.h - Exports for attribute list attribute handling. * attrlist.h - Exports for attribute list attribute handling.
* Originated from Linux-NTFS project. * Originated from Linux-NTFS project.
* *
* Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2004 Yura Pakhuchiy * Copyright (c) 2004 Yura Pakhuchiy
@ -26,26 +26,26 @@
#include "attrib.h" #include "attrib.h"
extern int ntfs_attrlist_need(ntfs_inode *ni); extern int ntfs_attrlist_need( ntfs_inode *ni );
extern int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr); extern int ntfs_attrlist_entry_add( ntfs_inode *ni, ATTR_RECORD *attr );
extern int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx); extern int ntfs_attrlist_entry_rm( ntfs_attr_search_ctx *ctx );
/** /**
* ntfs_attrlist_mark_dirty - set the attribute list dirty * ntfs_attrlist_mark_dirty - set the attribute list dirty
* @ni: ntfs inode which base inode contain dirty attribute list * @ni: ntfs inode which base inode contain dirty attribute list
* *
* Set the attribute list dirty so it is written out later (at the latest at * Set the attribute list dirty so it is written out later (at the latest at
* ntfs_inode_close() time). * ntfs_inode_close() time).
* *
* This function cannot fail. * This function cannot fail.
*/ */
static __inline__ void ntfs_attrlist_mark_dirty(ntfs_inode *ni) static __inline__ void ntfs_attrlist_mark_dirty( ntfs_inode *ni )
{ {
if (ni->nr_extents == -1) if ( ni->nr_extents == -1 )
NInoAttrListSetDirty(ni->base_ni); NInoAttrListSetDirty( ni->base_ni );
else else
NInoAttrListSetDirty(ni); NInoAttrListSetDirty( ni );
} }
#endif /* defined _NTFS_ATTRLIST_H */ #endif /* defined _NTFS_ATTRLIST_H */

View File

@ -3,7 +3,7 @@
Functions for dealing with conversion of data between types Functions for dealing with conversion of data between types
Copyright (c) 2006 Michael "Chishm" Chisholm Copyright (c) 2006 Michael "Chishm" Chisholm
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
@ -34,24 +34,28 @@
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
Functions to deal with little endian values stored in uint8_t arrays Functions to deal with little endian values stored in uint8_t arrays
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
static inline uint16_t u8array_to_u16 (const uint8_t* item, int offset) { static inline uint16_t u8array_to_u16 ( const uint8_t* item, int offset )
return ( item[offset] | (item[offset + 1] << 8)); {
return ( item[offset] | ( item[offset + 1] << 8 ) );
} }
static inline uint32_t u8array_to_u32 (const uint8_t* item, int offset) { static inline uint32_t u8array_to_u32 ( const uint8_t* item, int offset )
return ( item[offset] | (item[offset + 1] << 8) | (item[offset + 2] << 16) | (item[offset + 3] << 24)); {
return ( item[offset] | ( item[offset + 1] << 8 ) | ( item[offset + 2] << 16 ) | ( item[offset + 3] << 24 ) );
} }
static inline void u16_to_u8array (uint8_t* item, int offset, uint16_t value) { static inline void u16_to_u8array ( uint8_t* item, int offset, uint16_t value )
item[offset] = (uint8_t) value; {
item[offset + 1] = (uint8_t)(value >> 8); item[offset] = ( uint8_t ) value;
item[offset + 1] = ( uint8_t )( value >> 8 );
} }
static inline void u32_to_u8array (uint8_t* item, int offset, uint32_t value) { static inline void u32_to_u8array ( uint8_t* item, int offset, uint32_t value )
item[offset] = (uint8_t) value; {
item[offset + 1] = (uint8_t)(value >> 8); item[offset] = ( uint8_t ) value;
item[offset + 2] = (uint8_t)(value >> 16); item[offset + 1] = ( uint8_t )( value >> 8 );
item[offset + 3] = (uint8_t)(value >> 24); item[offset + 2] = ( uint8_t )( value >> 16 );
item[offset + 3] = ( uint8_t )( value >> 24 );
} }
#endif // _BIT_OPS_H #endif // _BIT_OPS_H

View File

@ -47,254 +47,268 @@
/** /**
* ntfs_bit_set - set a bit in a field of bits * ntfs_bit_set - set a bit in a field of bits
* @bitmap: field of bits * @bitmap: field of bits
* @bit: bit to set * @bit: bit to set
* @new_value: value to set bit to (0 or 1) * @new_value: value to set bit to (0 or 1)
* *
* Set the bit @bit in the @bitmap to @new_value. Ignore all errors. * Set the bit @bit in the @bitmap to @new_value. Ignore all errors.
*/ */
void ntfs_bit_set(u8 *bitmap, const u64 bit, const u8 new_value) void ntfs_bit_set( u8 *bitmap, const u64 bit, const u8 new_value )
{ {
if (!bitmap || new_value > 1) if ( !bitmap || new_value > 1 )
return; return;
if (!new_value) if ( !new_value )
bitmap[bit >> 3] &= ~(1 << (bit & 7)); bitmap[bit >> 3] &= ~( 1 << ( bit & 7 ) );
else else
bitmap[bit >> 3] |= (1 << (bit & 7)); bitmap[bit >> 3] |= ( 1 << ( bit & 7 ) );
} }
/** /**
* ntfs_bit_get - get value of a bit in a field of bits * ntfs_bit_get - get value of a bit in a field of bits
* @bitmap: field of bits * @bitmap: field of bits
* @bit: bit to get * @bit: bit to get
* *
* Get and return the value of the bit @bit in @bitmap (0 or 1). * Get and return the value of the bit @bit in @bitmap (0 or 1).
* Return -1 on error. * Return -1 on error.
*/ */
char ntfs_bit_get(const u8 *bitmap, const u64 bit) char ntfs_bit_get( const u8 *bitmap, const u64 bit )
{ {
if (!bitmap) if ( !bitmap )
return -1; return -1;
return (bitmap[bit >> 3] >> (bit & 7)) & 1; return ( bitmap[bit >> 3] >> ( bit & 7 ) ) & 1;
} }
/** /**
* ntfs_bit_get_and_set - get value of a bit in a field of bits and set it * ntfs_bit_get_and_set - get value of a bit in a field of bits and set it
* @bitmap: field of bits * @bitmap: field of bits
* @bit: bit to get/set * @bit: bit to get/set
* @new_value: value to set bit to (0 or 1) * @new_value: value to set bit to (0 or 1)
* *
* Return the value of the bit @bit and set it to @new_value (0 or 1). * Return the value of the bit @bit and set it to @new_value (0 or 1).
* Return -1 on error. * Return -1 on error.
*/ */
char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, const u8 new_value) char ntfs_bit_get_and_set( u8 *bitmap, const u64 bit, const u8 new_value )
{ {
register u8 old_bit, shift; register u8 old_bit, shift;
if (!bitmap || new_value > 1) if ( !bitmap || new_value > 1 )
return -1; return -1;
shift = bit & 7; shift = bit & 7;
old_bit = (bitmap[bit >> 3] >> shift) & 1; old_bit = ( bitmap[bit >> 3] >> shift ) & 1;
if (new_value != old_bit) if ( new_value != old_bit )
bitmap[bit >> 3] ^= 1 << shift; bitmap[bit >> 3] ^= 1 << shift;
return old_bit; return old_bit;
} }
/** /**
* ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value
* @na: attribute containing the bitmap * @na: attribute containing the bitmap
* @start_bit: first bit to set * @start_bit: first bit to set
* @count: number of bits to set * @count: number of bits to set
* @value: value to set the bits to (i.e. 0 or 1) * @value: value to set the bits to (i.e. 0 or 1)
* *
* Set @count bits starting at bit @start_bit in the bitmap described by the * Set @count bits starting at bit @start_bit in the bitmap described by the
* attribute @na to @value, where @value is either 0 or 1. * attribute @na to @value, where @value is either 0 or 1.
* *
* On success return 0 and on error return -1 with errno set to the error code. * On success return 0 and on error return -1 with errno set to the error code.
*/ */
static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit, static int ntfs_bitmap_set_bits_in_run( ntfs_attr *na, s64 start_bit,
s64 count, int value) s64 count, int value )
{ {
s64 bufsize, br; s64 bufsize, br;
u8 *buf, *lastbyte_buf; u8 *buf, *lastbyte_buf;
int bit, firstbyte, lastbyte, lastbyte_pos, tmp, ret = -1; int bit, firstbyte, lastbyte, lastbyte_pos, tmp, ret = -1;
if (!na || start_bit < 0 || count < 0) { if ( !na || start_bit < 0 || count < 0 )
errno = EINVAL; {
ntfs_log_perror("%s: Invalid argument (%p, %lld, %lld)", errno = EINVAL;
__FUNCTION__, na, (long long)start_bit, (long long)count); ntfs_log_perror( "%s: Invalid argument (%p, %lld, %lld)",
return -1; __FUNCTION__, na, ( long long )start_bit, ( long long )count );
} return -1;
}
bit = start_bit & 7; bit = start_bit & 7;
if (bit) if ( bit )
firstbyte = 1; firstbyte = 1;
else else
firstbyte = 0; firstbyte = 0;
/* Calculate the required buffer size in bytes, capping it at 8kiB. */ /* Calculate the required buffer size in bytes, capping it at 8kiB. */
bufsize = ((count - (bit ? 8 - bit : 0) + 7) >> 3) + firstbyte; bufsize = ( ( count - ( bit ? 8 - bit : 0 ) + 7 ) >> 3 ) + firstbyte;
if (bufsize > 8192) if ( bufsize > 8192 )
bufsize = 8192; bufsize = 8192;
buf = ntfs_malloc(bufsize); buf = ntfs_malloc( bufsize );
if (!buf) if ( !buf )
return -1; return -1;
/* Depending on @value, zero or set all bits in the allocated buffer. */
memset(buf, value ? 0xff : 0, bufsize);
/* If there is a first partial byte... */ /* Depending on @value, zero or set all bits in the allocated buffer. */
if (bit) { memset( buf, value ? 0xff : 0, bufsize );
/* read it in... */
br = ntfs_attr_pread(na, start_bit >> 3, 1, buf);
if (br != 1) {
if (br >= 0)
errno = EIO;
goto free_err_out;
}
/* and set or clear the appropriate bits in it. */
while ((bit & 7) && count--) {
if (value)
*buf |= 1 << bit++;
else
*buf &= ~(1 << bit++);
}
/* Update @start_bit to the new position. */
start_bit = (start_bit + 7) & ~7;
}
/* Loop until @count reaches zero. */ /* If there is a first partial byte... */
lastbyte = 0; if ( bit )
lastbyte_buf = NULL; {
bit = count & 7; /* read it in... */
do { br = ntfs_attr_pread( na, start_bit >> 3, 1, buf );
/* If there is a last partial byte... */ if ( br != 1 )
if (count > 0 && bit) { {
lastbyte_pos = ((count + 7) >> 3) + firstbyte; if ( br >= 0 )
if (!lastbyte_pos) { errno = EIO;
// FIXME: Eeek! BUG! goto free_err_out;
ntfs_log_error("Lastbyte is zero. Leaving " }
"inconsistent metadata.\n"); /* and set or clear the appropriate bits in it. */
errno = EIO; while ( ( bit & 7 ) && count-- )
goto free_err_out; {
} if ( value )
/* and it is in the currently loaded bitmap window... */ *buf |= 1 << bit++;
if (lastbyte_pos <= bufsize) { else
lastbyte_buf = buf + lastbyte_pos - 1; *buf &= ~( 1 << bit++ );
}
/* Update @start_bit to the new position. */
start_bit = ( start_bit + 7 ) & ~7;
}
/* read the byte in... */ /* Loop until @count reaches zero. */
br = ntfs_attr_pread(na, (start_bit + count) >> lastbyte = 0;
3, 1, lastbyte_buf); lastbyte_buf = NULL;
if (br != 1) { bit = count & 7;
// FIXME: Eeek! We need rollback! (AIA) do
if (br >= 0) {
errno = EIO; /* If there is a last partial byte... */
ntfs_log_perror("Reading of last byte " if ( count > 0 && bit )
"failed (%lld). Leaving inconsistent " {
"metadata", (long long)br); lastbyte_pos = ( ( count + 7 ) >> 3 ) + firstbyte;
goto free_err_out; if ( !lastbyte_pos )
} {
/* and set/clear the appropriate bits in it. */ // FIXME: Eeek! BUG!
while (bit && count--) { ntfs_log_error( "Lastbyte is zero. Leaving "
if (value) "inconsistent metadata.\n" );
*lastbyte_buf |= 1 << --bit; errno = EIO;
else goto free_err_out;
*lastbyte_buf &= ~(1 << --bit); }
} /* and it is in the currently loaded bitmap window... */
/* We don't want to come back here... */ if ( lastbyte_pos <= bufsize )
bit = 0; {
/* We have a last byte that we have handled. */ lastbyte_buf = buf + lastbyte_pos - 1;
lastbyte = 1;
}
}
/* Write the prepared buffer to disk. */ /* read the byte in... */
tmp = (start_bit >> 3) - firstbyte; br = ntfs_attr_pread( na, ( start_bit + count ) >>
br = ntfs_attr_pwrite(na, tmp, bufsize, buf); 3, 1, lastbyte_buf );
if (br != bufsize) { if ( br != 1 )
// FIXME: Eeek! We need rollback! (AIA) {
if (br >= 0) // FIXME: Eeek! We need rollback! (AIA)
errno = EIO; if ( br >= 0 )
ntfs_log_perror("Failed to write buffer to bitmap " errno = EIO;
"(%lld != %lld). Leaving inconsistent metadata", ntfs_log_perror( "Reading of last byte "
(long long)br, (long long)bufsize); "failed (%lld). Leaving inconsistent "
goto free_err_out; "metadata", ( long long )br );
} goto free_err_out;
}
/* and set/clear the appropriate bits in it. */
while ( bit && count-- )
{
if ( value )
*lastbyte_buf |= 1 << --bit;
else
*lastbyte_buf &= ~( 1 << --bit );
}
/* We don't want to come back here... */
bit = 0;
/* We have a last byte that we have handled. */
lastbyte = 1;
}
}
/* Update counters. */ /* Write the prepared buffer to disk. */
tmp = (bufsize - firstbyte - lastbyte) << 3; tmp = ( start_bit >> 3 ) - firstbyte;
if (firstbyte) { br = ntfs_attr_pwrite( na, tmp, bufsize, buf );
firstbyte = 0; if ( br != bufsize )
/* {
* Re-set the partial first byte so a subsequent write // FIXME: Eeek! We need rollback! (AIA)
* of the buffer does not have stale, incorrect bits. if ( br >= 0 )
*/ errno = EIO;
*buf = value ? 0xff : 0; ntfs_log_perror( "Failed to write buffer to bitmap "
} "(%lld != %lld). Leaving inconsistent metadata",
start_bit += tmp; ( long long )br, ( long long )bufsize );
count -= tmp; goto free_err_out;
if (bufsize > (tmp = (count + 7) >> 3)) }
bufsize = tmp;
/* Update counters. */
tmp = ( bufsize - firstbyte - lastbyte ) << 3;
if ( firstbyte )
{
firstbyte = 0;
/*
* Re-set the partial first byte so a subsequent write
* of the buffer does not have stale, incorrect bits.
*/
*buf = value ? 0xff : 0;
}
start_bit += tmp;
count -= tmp;
if ( bufsize > ( tmp = ( count + 7 ) >> 3 ) )
bufsize = tmp;
if ( lastbyte && count != 0 )
{
// FIXME: Eeek! BUG!
ntfs_log_error( "Last buffer but count is not zero "
"(%lld). Leaving inconsistent metadata.\n",
( long long )count );
errno = EIO;
goto free_err_out;
}
}
while ( count > 0 );
ret = 0;
if (lastbyte && count != 0) {
// FIXME: Eeek! BUG!
ntfs_log_error("Last buffer but count is not zero "
"(%lld). Leaving inconsistent metadata.\n",
(long long)count);
errno = EIO;
goto free_err_out;
}
} while (count > 0);
ret = 0;
free_err_out: free_err_out:
free(buf); free( buf );
return ret; return ret;
} }
/** /**
* ntfs_bitmap_set_run - set a run of bits in a bitmap * ntfs_bitmap_set_run - set a run of bits in a bitmap
* @na: attribute containing the bitmap * @na: attribute containing the bitmap
* @start_bit: first bit to set * @start_bit: first bit to set
* @count: number of bits to set * @count: number of bits to set
* *
* Set @count bits starting at bit @start_bit in the bitmap described by the * Set @count bits starting at bit @start_bit in the bitmap described by the
* attribute @na. * attribute @na.
* *
* On success return 0 and on error return -1 with errno set to the error code. * On success return 0 and on error return -1 with errno set to the error code.
*/ */
int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count) int ntfs_bitmap_set_run( ntfs_attr *na, s64 start_bit, s64 count )
{ {
int ret; int ret;
ntfs_log_enter("Set from bit %lld, count %lld\n", ntfs_log_enter( "Set from bit %lld, count %lld\n",
(long long)start_bit, (long long)count); ( long long )start_bit, ( long long )count );
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1); ret = ntfs_bitmap_set_bits_in_run( na, start_bit, count, 1 );
ntfs_log_leave("\n"); ntfs_log_leave( "\n" );
return ret; return ret;
} }
/** /**
* ntfs_bitmap_clear_run - clear a run of bits in a bitmap * ntfs_bitmap_clear_run - clear a run of bits in a bitmap
* @na: attribute containing the bitmap * @na: attribute containing the bitmap
* @start_bit: first bit to clear * @start_bit: first bit to clear
* @count: number of bits to clear * @count: number of bits to clear
* *
* Clear @count bits starting at bit @start_bit in the bitmap described by the * Clear @count bits starting at bit @start_bit in the bitmap described by the
* attribute @na. * attribute @na.
* *
* On success return 0 and on error return -1 with errno set to the error code. * On success return 0 and on error return -1 with errno set to the error code.
*/ */
int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count) int ntfs_bitmap_clear_run( ntfs_attr *na, s64 start_bit, s64 count )
{ {
int ret; int ret;
ntfs_log_enter("Clear from bit %lld, count %lld\n", ntfs_log_enter( "Clear from bit %lld, count %lld\n",
(long long)start_bit, (long long)count); ( long long )start_bit, ( long long )count );
ret = ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0); ret = ntfs_bitmap_set_bits_in_run( na, start_bit, count, 0 );
ntfs_log_leave("\n"); ntfs_log_leave( "\n" );
return ret; return ret;
} }

View File

@ -36,38 +36,38 @@
* size of the bitmap. * size of the bitmap.
*/ */
extern void ntfs_bit_set(u8 *bitmap, const u64 bit, const u8 new_value); extern void ntfs_bit_set( u8 *bitmap, const u64 bit, const u8 new_value );
extern char ntfs_bit_get(const u8 *bitmap, const u64 bit); extern char ntfs_bit_get( const u8 *bitmap, const u64 bit );
extern char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, const u8 new_value); extern char ntfs_bit_get_and_set( u8 *bitmap, const u64 bit, const u8 new_value );
extern int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count); extern int ntfs_bitmap_set_run( ntfs_attr *na, s64 start_bit, s64 count );
extern int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count); extern int ntfs_bitmap_clear_run( ntfs_attr *na, s64 start_bit, s64 count );
/** /**
* ntfs_bitmap_set_bit - set a bit in a bitmap * ntfs_bitmap_set_bit - set a bit in a bitmap
* @na: attribute containing the bitmap * @na: attribute containing the bitmap
* @bit: bit to set * @bit: bit to set
* *
* Set the @bit in the bitmap described by the attribute @na. * Set the @bit in the bitmap described by the attribute @na.
* *
* On success return 0 and on error return -1 with errno set to the error code. * On success return 0 and on error return -1 with errno set to the error code.
*/ */
static __inline__ int ntfs_bitmap_set_bit(ntfs_attr *na, s64 bit) static __inline__ int ntfs_bitmap_set_bit( ntfs_attr *na, s64 bit )
{ {
return ntfs_bitmap_set_run(na, bit, 1); return ntfs_bitmap_set_run( na, bit, 1 );
} }
/** /**
* ntfs_bitmap_clear_bit - clear a bit in a bitmap * ntfs_bitmap_clear_bit - clear a bit in a bitmap
* @na: attribute containing the bitmap * @na: attribute containing the bitmap
* @bit: bit to clear * @bit: bit to clear
* *
* Clear @bit in the bitmap described by the attribute @na. * Clear @bit in the bitmap described by the attribute @na.
* *
* On success return 0 and on error return -1 with errno set to the error code. * On success return 0 and on error return -1 with errno set to the error code.
*/ */
static __inline__ int ntfs_bitmap_clear_bit(ntfs_attr *na, s64 bit) static __inline__ int ntfs_bitmap_clear_bit( ntfs_attr *na, s64 bit )
{ {
return ntfs_bitmap_clear_run(na, bit, 1); return ntfs_bitmap_clear_run( na, bit, 1 );
} }
/* /*
@ -76,9 +76,9 @@ static __inline__ int ntfs_bitmap_clear_bit(ntfs_attr *na, s64 bit)
* @word: value to rotate * @word: value to rotate
* @shift: bits to roll * @shift: bits to roll
*/ */
static __inline__ u32 ntfs_rol32(u32 word, unsigned int shift) static __inline__ u32 ntfs_rol32( u32 word, unsigned int shift )
{ {
return (word << shift) | (word >> (32 - shift)); return ( word << shift ) | ( word >> ( 32 - shift ) );
} }
/* /*
@ -87,9 +87,9 @@ static __inline__ u32 ntfs_rol32(u32 word, unsigned int shift)
* @word: value to rotate * @word: value to rotate
* @shift: bits to roll * @shift: bits to roll
*/ */
static __inline__ u32 ntfs_ror32(u32 word, unsigned int shift) static __inline__ u32 ntfs_ror32( u32 word, unsigned int shift )
{ {
return (word >> shift) | (word << (32 - shift)); return ( word >> shift ) | ( word << ( 32 - shift ) );
} }
#endif /* defined _NTFS_BITMAP_H */ #endif /* defined _NTFS_BITMAP_H */

View File

@ -45,8 +45,8 @@
/** /**
* ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector * ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector
* @b: buffer containing putative boot sector to analyze * @b: buffer containing putative boot sector to analyze
* @silent: if zero, output progress messages to stderr * @silent: if zero, output progress messages to stderr
* *
* Check if the buffer @b contains a valid ntfs boot sector. The buffer @b * Check if the buffer @b contains a valid ntfs boot sector. The buffer @b
* must be at least 512 bytes in size. * must be at least 512 bytes in size.
@ -57,229 +57,244 @@
* *
* Return TRUE if @b contains a valid ntfs boot sector and FALSE if not. * Return TRUE if @b contains a valid ntfs boot sector and FALSE if not.
*/ */
BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b) BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b )
{ {
u32 i; u32 i;
BOOL ret = FALSE; BOOL ret = FALSE;
ntfs_log_debug("Beginning bootsector check.\n"); ntfs_log_debug( "Beginning bootsector check.\n" );
ntfs_log_debug("Checking OEMid, NTFS signature.\n"); ntfs_log_debug( "Checking OEMid, NTFS signature.\n" );
if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) { /* "NTFS " */ if ( b->oem_id != cpu_to_le64( 0x202020205346544eULL ) ) /* "NTFS " */
ntfs_log_error("NTFS signature is missing.\n"); {
goto not_ntfs; ntfs_log_error( "NTFS signature is missing.\n" );
} goto not_ntfs;
}
ntfs_log_debug("Checking bytes per sector.\n"); ntfs_log_debug( "Checking bytes per sector.\n" );
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 || if ( le16_to_cpu( b->bpb.bytes_per_sector ) < 256 ||
le16_to_cpu(b->bpb.bytes_per_sector) > 4096) { le16_to_cpu( b->bpb.bytes_per_sector ) > 4096 )
ntfs_log_error("Unexpected bytes per sector value (%d).\n", {
le16_to_cpu(b->bpb.bytes_per_sector)); ntfs_log_error( "Unexpected bytes per sector value (%d).\n",
goto not_ntfs; le16_to_cpu( b->bpb.bytes_per_sector ) );
} goto not_ntfs;
}
ntfs_log_debug("Checking sectors per cluster.\n"); ntfs_log_debug( "Checking sectors per cluster.\n" );
switch (b->bpb.sectors_per_cluster) { switch ( b->bpb.sectors_per_cluster )
case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: {
break; case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128:
default: break;
ntfs_log_error("Unexpected sectors per cluster value (%d).\n", default:
b->bpb.sectors_per_cluster); ntfs_log_error( "Unexpected sectors per cluster value (%d).\n",
goto not_ntfs; b->bpb.sectors_per_cluster );
} goto not_ntfs;
}
ntfs_log_debug("Checking cluster size.\n"); ntfs_log_debug( "Checking cluster size.\n" );
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * i = ( u32 )le16_to_cpu( b->bpb.bytes_per_sector ) *
b->bpb.sectors_per_cluster; b->bpb.sectors_per_cluster;
if (i > 65536) { if ( i > 65536 )
ntfs_log_error("Unexpected cluster size (%d).\n", i); {
goto not_ntfs; ntfs_log_error( "Unexpected cluster size (%d).\n", i );
} goto not_ntfs;
}
ntfs_log_debug("Checking reserved fields are zero.\n"); ntfs_log_debug( "Checking reserved fields are zero.\n" );
if (le16_to_cpu(b->bpb.reserved_sectors) || if ( le16_to_cpu( b->bpb.reserved_sectors ) ||
le16_to_cpu(b->bpb.root_entries) || le16_to_cpu( b->bpb.root_entries ) ||
le16_to_cpu(b->bpb.sectors) || le16_to_cpu( b->bpb.sectors ) ||
le16_to_cpu(b->bpb.sectors_per_fat) || le16_to_cpu( b->bpb.sectors_per_fat ) ||
le32_to_cpu(b->bpb.large_sectors) || le32_to_cpu( b->bpb.large_sectors ) ||
b->bpb.fats) { b->bpb.fats )
ntfs_log_error("Reserved fields aren't zero " {
"(%d, %d, %d, %d, %d, %d).\n", ntfs_log_error( "Reserved fields aren't zero "
le16_to_cpu(b->bpb.reserved_sectors), "(%d, %d, %d, %d, %d, %d).\n",
le16_to_cpu(b->bpb.root_entries), le16_to_cpu( b->bpb.reserved_sectors ),
le16_to_cpu(b->bpb.sectors), le16_to_cpu( b->bpb.root_entries ),
le16_to_cpu(b->bpb.sectors_per_fat), le16_to_cpu( b->bpb.sectors ),
le32_to_cpu(b->bpb.large_sectors), le16_to_cpu( b->bpb.sectors_per_fat ),
b->bpb.fats); le32_to_cpu( b->bpb.large_sectors ),
goto not_ntfs; b->bpb.fats );
} goto not_ntfs;
}
ntfs_log_debug("Checking clusters per mft record.\n"); ntfs_log_debug( "Checking clusters per mft record.\n" );
if ((u8)b->clusters_per_mft_record < 0xe1 || if ( ( u8 )b->clusters_per_mft_record < 0xe1 ||
(u8)b->clusters_per_mft_record > 0xf7) { ( u8 )b->clusters_per_mft_record > 0xf7 )
switch (b->clusters_per_mft_record) { {
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: switch ( b->clusters_per_mft_record )
break; {
default: case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
ntfs_log_error("Unexpected clusters per mft record " break;
"(%d).\n", b->clusters_per_mft_record); default:
goto not_ntfs; ntfs_log_error( "Unexpected clusters per mft record "
} "(%d).\n", b->clusters_per_mft_record );
} goto not_ntfs;
}
}
ntfs_log_debug("Checking clusters per index block.\n"); ntfs_log_debug( "Checking clusters per index block.\n" );
if ((u8)b->clusters_per_index_record < 0xe1 || if ( ( u8 )b->clusters_per_index_record < 0xe1 ||
(u8)b->clusters_per_index_record > 0xf7) { ( u8 )b->clusters_per_index_record > 0xf7 )
switch (b->clusters_per_index_record) { {
case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: switch ( b->clusters_per_index_record )
break; {
default: case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40:
ntfs_log_error("Unexpected clusters per index record " break;
"(%d).\n", b->clusters_per_index_record); default:
goto not_ntfs; ntfs_log_error( "Unexpected clusters per index record "
} "(%d).\n", b->clusters_per_index_record );
} goto not_ntfs;
}
}
if (b->end_of_sector_marker != cpu_to_le16(0xaa55)) if ( b->end_of_sector_marker != cpu_to_le16( 0xaa55 ) )
ntfs_log_debug("Warning: Bootsector has invalid end of sector " ntfs_log_debug( "Warning: Bootsector has invalid end of sector "
"marker.\n"); "marker.\n" );
ntfs_log_debug("Bootsector check completed successfully.\n"); ntfs_log_debug( "Bootsector check completed successfully.\n" );
ret = TRUE; ret = TRUE;
not_ntfs: not_ntfs:
return ret; return ret;
} }
static const char *last_sector_error = static const char *last_sector_error =
"HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n" "HINTS: Either the volume is a RAID/LDM but it wasn't setup yet,\n"
" or it was not setup correctly (e.g. by not using mdadm --build ...),\n" " or it was not setup correctly (e.g. by not using mdadm --build ...),\n"
" or a wrong device is tried to be mounted,\n" " or a wrong device is tried to be mounted,\n"
" or the partition table is corrupt (partition is smaller than NTFS),\n" " or the partition table is corrupt (partition is smaller than NTFS),\n"
" or the NTFS boot sector is corrupt (NTFS size is not valid).\n"; " or the NTFS boot sector is corrupt (NTFS size is not valid).\n";
/** /**
* ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector * ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector
* @vol: ntfs_volume to setup * @vol: ntfs_volume to setup
* @bs: buffer containing ntfs boot sector to parse * @bs: buffer containing ntfs boot sector to parse
* *
* Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the * Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the
* obtained values. * obtained values.
* *
* Return 0 on success or -1 on error with errno set to the error code EINVAL. * Return 0 on success or -1 on error with errno set to the error code EINVAL.
*/ */
int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs) int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs )
{ {
s64 sectors; s64 sectors;
u8 sectors_per_cluster; u8 sectors_per_cluster;
s8 c; s8 c;
/* We return -1 with errno = EINVAL on error. */ /* We return -1 with errno = EINVAL on error. */
errno = EINVAL; errno = EINVAL;
vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector); vol->sector_size = le16_to_cpu( bs->bpb.bytes_per_sector );
vol->sector_size_bits = ffs(vol->sector_size) - 1; vol->sector_size_bits = ffs( vol->sector_size ) - 1;
ntfs_log_debug("SectorSize = 0x%x\n", vol->sector_size); ntfs_log_debug( "SectorSize = 0x%x\n", vol->sector_size );
ntfs_log_debug("SectorSizeBits = %u\n", vol->sector_size_bits); ntfs_log_debug( "SectorSizeBits = %u\n", vol->sector_size_bits );
/* /*
* The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being
* below or equal the number_of_clusters) really belong in the * below or equal the number_of_clusters) really belong in the
* ntfs_boot_sector_is_ntfs but in this way we can just do this once. * ntfs_boot_sector_is_ntfs but in this way we can just do this once.
*/ */
sectors_per_cluster = bs->bpb.sectors_per_cluster; sectors_per_cluster = bs->bpb.sectors_per_cluster;
ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster); ntfs_log_debug( "SectorsPerCluster = 0x%x\n", sectors_per_cluster );
if (sectors_per_cluster & (sectors_per_cluster - 1)) { if ( sectors_per_cluster & ( sectors_per_cluster - 1 ) )
ntfs_log_error("sectors_per_cluster (%d) is not a power of 2." {
"\n", sectors_per_cluster); ntfs_log_error( "sectors_per_cluster (%d) is not a power of 2."
return -1; "\n", sectors_per_cluster );
} return -1;
}
sectors = sle64_to_cpu(bs->number_of_sectors);
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
if (!sectors) {
ntfs_log_error("Volume size is set to zero.\n");
return -1;
}
if (vol->dev->d_ops->seek(vol->dev,
(sectors - 1) << vol->sector_size_bits,
SEEK_SET) == -1) {
ntfs_log_perror("Failed to read last sector (%lld)",
(long long)sectors);
ntfs_log_error("%s", last_sector_error);
return -1;
}
vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1);
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn); sectors = sle64_to_cpu( bs->number_of_sectors );
vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn); ntfs_log_debug( "NumberOfSectors = %lld\n", ( long long )sectors );
ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn); if ( !sectors )
ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn); {
if (vol->mft_lcn > vol->nr_clusters || ntfs_log_error( "Volume size is set to zero.\n" );
vol->mftmirr_lcn > vol->nr_clusters) { return -1;
ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is " }
"greater than the number of clusters (%lld).\n", if ( vol->dev->d_ops->seek( vol->dev,
(long long)vol->mft_lcn, (long long)vol->mftmirr_lcn, ( sectors - 1 ) << vol->sector_size_bits,
(long long)vol->nr_clusters); SEEK_SET ) == -1 )
return -1; {
} ntfs_log_perror( "Failed to read last sector (%lld)",
( long long )sectors );
vol->cluster_size = sectors_per_cluster * vol->sector_size; ntfs_log_error( "%s", last_sector_error );
if (vol->cluster_size & (vol->cluster_size - 1)) { return -1;
ntfs_log_error("cluster_size (%d) is not a power of 2.\n", }
vol->cluster_size);
return -1; vol->nr_clusters = sectors >> ( ffs( sectors_per_cluster ) - 1 );
}
vol->cluster_size_bits = ffs(vol->cluster_size) - 1; vol->mft_lcn = sle64_to_cpu( bs->mft_lcn );
/* vol->mftmirr_lcn = sle64_to_cpu( bs->mftmirr_lcn );
* Need to get the clusters per mft record and handle it if it is ntfs_log_debug( "MFT LCN = %lld\n", ( long long )vol->mft_lcn );
* negative. Then calculate the mft_record_size. A value of 0x80 is ntfs_log_debug( "MFTMirr LCN = %lld\n", ( long long )vol->mftmirr_lcn );
* illegal, thus signed char is actually ok! if ( vol->mft_lcn > vol->nr_clusters ||
*/ vol->mftmirr_lcn > vol->nr_clusters )
c = bs->clusters_per_mft_record; {
ntfs_log_debug("ClusterSize = 0x%x\n", (unsigned)vol->cluster_size); ntfs_log_error( "$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
ntfs_log_debug("ClusterSizeBits = %u\n", vol->cluster_size_bits); "greater than the number of clusters (%lld).\n",
ntfs_log_debug("ClustersPerMftRecord = 0x%x\n", c); ( long long )vol->mft_lcn, ( long long )vol->mftmirr_lcn,
/* ( long long )vol->nr_clusters );
* When clusters_per_mft_record is negative, it means that it is to return -1;
* be taken to be the negative base 2 logarithm of the mft_record_size }
* min bytes. Then:
* mft_record_size = 2^(-clusters_per_mft_record) bytes. vol->cluster_size = sectors_per_cluster * vol->sector_size;
*/ if ( vol->cluster_size & ( vol->cluster_size - 1 ) )
if (c < 0) {
vol->mft_record_size = 1 << -c; ntfs_log_error( "cluster_size (%d) is not a power of 2.\n",
else vol->cluster_size );
vol->mft_record_size = c << vol->cluster_size_bits; return -1;
if (vol->mft_record_size & (vol->mft_record_size - 1)) { }
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n", vol->cluster_size_bits = ffs( vol->cluster_size ) - 1;
vol->mft_record_size); /*
return -1; * Need to get the clusters per mft record and handle it if it is
} * negative. Then calculate the mft_record_size. A value of 0x80 is
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; * illegal, thus signed char is actually ok!
ntfs_log_debug("MftRecordSize = 0x%x\n", (unsigned)vol->mft_record_size); */
ntfs_log_debug("MftRecordSizeBits = %u\n", vol->mft_record_size_bits); c = bs->clusters_per_mft_record;
/* Same as above for INDX record. */ ntfs_log_debug( "ClusterSize = 0x%x\n", ( unsigned )vol->cluster_size );
c = bs->clusters_per_index_record; ntfs_log_debug( "ClusterSizeBits = %u\n", vol->cluster_size_bits );
ntfs_log_debug("ClustersPerINDXRecord = 0x%x\n", c); ntfs_log_debug( "ClustersPerMftRecord = 0x%x\n", c );
if (c < 0) /*
vol->indx_record_size = 1 << -c; * When clusters_per_mft_record is negative, it means that it is to
else * be taken to be the negative base 2 logarithm of the mft_record_size
vol->indx_record_size = c << vol->cluster_size_bits; * min bytes. Then:
vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1; * mft_record_size = 2^(-clusters_per_mft_record) bytes.
ntfs_log_debug("INDXRecordSize = 0x%x\n", (unsigned)vol->indx_record_size); */
ntfs_log_debug("INDXRecordSizeBits = %u\n", vol->indx_record_size_bits); if ( c < 0 )
/* vol->mft_record_size = 1 << -c;
* Work out the size of the MFT mirror in number of mft records. If the else
* cluster size is less than or equal to the size taken by four mft vol->mft_record_size = c << vol->cluster_size_bits;
* records, the mft mirror stores the first four mft records. If the if ( vol->mft_record_size & ( vol->mft_record_size - 1 ) )
* cluster size is bigger than the size taken by four mft records, the {
* mft mirror contains as many mft records as will fit into one ntfs_log_error( "mft_record_size (%d) is not a power of 2.\n",
* cluster. vol->mft_record_size );
*/ return -1;
if (vol->cluster_size <= 4 * vol->mft_record_size) }
vol->mftmirr_size = 4; vol->mft_record_size_bits = ffs( vol->mft_record_size ) - 1;
else ntfs_log_debug( "MftRecordSize = 0x%x\n", ( unsigned )vol->mft_record_size );
vol->mftmirr_size = vol->cluster_size / vol->mft_record_size; ntfs_log_debug( "MftRecordSizeBits = %u\n", vol->mft_record_size_bits );
return 0; /* Same as above for INDX record. */
c = bs->clusters_per_index_record;
ntfs_log_debug( "ClustersPerINDXRecord = 0x%x\n", c );
if ( c < 0 )
vol->indx_record_size = 1 << -c;
else
vol->indx_record_size = c << vol->cluster_size_bits;
vol->indx_record_size_bits = ffs( vol->indx_record_size ) - 1;
ntfs_log_debug( "INDXRecordSize = 0x%x\n", ( unsigned )vol->indx_record_size );
ntfs_log_debug( "INDXRecordSizeBits = %u\n", vol->indx_record_size_bits );
/*
* Work out the size of the MFT mirror in number of mft records. If the
* cluster size is less than or equal to the size taken by four mft
* records, the mft mirror stores the first four mft records. If the
* cluster size is bigger than the size taken by four mft records, the
* mft mirror contains as many mft records as will fit into one
* cluster.
*/
if ( vol->cluster_size <= 4 * vol->mft_record_size )
vol->mftmirr_size = 4;
else
vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;
return 0;
} }

View File

@ -1,6 +1,6 @@
/* /*
* bootsect.h - Exports for bootsector record handling. * bootsect.h - Exports for bootsector record handling.
* Originated from the Linux-NTFS project. * Originated from the Linux-NTFS project.
* *
* Copyright (c) 2000-2002 Anton Altaparmakov * Copyright (c) 2000-2002 Anton Altaparmakov
* Copyright (c) 2006 Szabolcs Szakacsits * Copyright (c) 2006 Szabolcs Szakacsits
@ -30,13 +30,13 @@
/** /**
* ntfs_boot_sector_is_ntfs - check a boot sector for describing an ntfs volume * ntfs_boot_sector_is_ntfs - check a boot sector for describing an ntfs volume
* @b: buffer containing the boot sector * @b: buffer containing the boot sector
* *
* This function checks the boot sector in @b for describing a valid ntfs * This function checks the boot sector in @b for describing a valid ntfs
* volume. Return TRUE if @b is a valid NTFS boot sector or FALSE otherwise. * volume. Return TRUE if @b is a valid NTFS boot sector or FALSE otherwise.
*/ */
extern BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b); extern BOOL ntfs_boot_sector_is_ntfs( NTFS_BOOT_SECTOR *b );
extern int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs); extern int ntfs_boot_sector_parse( ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs );
#endif /* defined _NTFS_BOOTSECT_H */ #endif /* defined _NTFS_BOOTSECT_H */

File diff suppressed because it is too large Load Diff

View File

@ -24,96 +24,104 @@
#include "volume.h" #include "volume.h"
struct CACHED_GENERIC { struct CACHED_GENERIC
struct CACHED_GENERIC *next; {
struct CACHED_GENERIC *previous; struct CACHED_GENERIC *next;
void *variable; struct CACHED_GENERIC *previous;
size_t varsize; void *variable;
union { size_t varsize;
/* force alignment for pointers and u64 */ union
u64 u64align; {
void *ptralign; /* force alignment for pointers and u64 */
} fixed[0]; u64 u64align;
void *ptralign;
} fixed[0];
} ; } ;
struct CACHED_INODE { struct CACHED_INODE
struct CACHED_INODE *next; {
struct CACHED_INODE *previous; struct CACHED_INODE *next;
const char *pathname; struct CACHED_INODE *previous;
size_t varsize; const char *pathname;
/* above fields must match "struct CACHED_GENERIC" */ size_t varsize;
u64 inum; /* above fields must match "struct CACHED_GENERIC" */
u64 inum;
} ; } ;
struct CACHED_NIDATA { struct CACHED_NIDATA
struct CACHED_NIDATA *next; {
struct CACHED_NIDATA *previous; struct CACHED_NIDATA *next;
const char *pathname; /* not used */ struct CACHED_NIDATA *previous;
size_t varsize; /* not used */ const char *pathname; /* not used */
/* above fields must match "struct CACHED_GENERIC" */ size_t varsize; /* not used */
u64 inum; /* above fields must match "struct CACHED_GENERIC" */
ntfs_inode *ni; u64 inum;
ntfs_inode *ni;
} ; } ;
struct CACHED_LOOKUP { struct CACHED_LOOKUP
struct CACHED_LOOKUP *next; {
struct CACHED_LOOKUP *previous; struct CACHED_LOOKUP *next;
const char *name; struct CACHED_LOOKUP *previous;
size_t namesize; const char *name;
/* above fields must match "struct CACHED_GENERIC" */ size_t namesize;
u64 parent; /* above fields must match "struct CACHED_GENERIC" */
u64 inum; u64 parent;
u64 inum;
} ; } ;
enum { enum
CACHE_FREE = 1, {
CACHE_NOHASH = 2 CACHE_FREE = 1,
CACHE_NOHASH = 2
} ; } ;
typedef int (*cache_compare)(const struct CACHED_GENERIC *cached, typedef int ( *cache_compare )( const struct CACHED_GENERIC *cached,
const struct CACHED_GENERIC *item); const struct CACHED_GENERIC *item );
typedef void (*cache_free)(const struct CACHED_GENERIC *cached); typedef void ( *cache_free )( const struct CACHED_GENERIC *cached );
typedef int (*cache_hash)(const struct CACHED_GENERIC *cached); typedef int ( *cache_hash )( const struct CACHED_GENERIC *cached );
struct HASH_ENTRY { struct HASH_ENTRY
struct HASH_ENTRY *next; {
struct CACHED_GENERIC *entry; struct HASH_ENTRY *next;
struct CACHED_GENERIC *entry;
} ; } ;
struct CACHE_HEADER { struct CACHE_HEADER
const char *name; {
struct CACHED_GENERIC *most_recent_entry; const char *name;
struct CACHED_GENERIC *oldest_entry; struct CACHED_GENERIC *most_recent_entry;
struct CACHED_GENERIC *free_entry; struct CACHED_GENERIC *oldest_entry;
struct HASH_ENTRY *free_hash; struct CACHED_GENERIC *free_entry;
struct HASH_ENTRY **first_hash; struct HASH_ENTRY *free_hash;
cache_free dofree; struct HASH_ENTRY **first_hash;
cache_hash dohash; cache_free dofree;
unsigned long reads; cache_hash dohash;
unsigned long writes; unsigned long reads;
unsigned long hits; unsigned long writes;
int fixed_size; unsigned long hits;
int max_hash; int fixed_size;
struct CACHED_GENERIC entry[0]; int max_hash;
struct CACHED_GENERIC entry[0];
} ; } ;
/* cast to generic, avoiding gcc warnings */ /* cast to generic, avoiding gcc warnings */
#define GENERIC(pstr) ((const struct CACHED_GENERIC*)(const void*)(pstr)) #define GENERIC(pstr) ((const struct CACHED_GENERIC*)(const void*)(pstr))
struct CACHED_GENERIC *ntfs_fetch_cache(struct CACHE_HEADER *cache, struct CACHED_GENERIC *ntfs_fetch_cache( struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *wanted, const struct CACHED_GENERIC *wanted,
cache_compare compare); cache_compare compare );
struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache, struct CACHED_GENERIC *ntfs_enter_cache( struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item, const struct CACHED_GENERIC *item,
cache_compare compare); cache_compare compare );
int ntfs_invalidate_cache(struct CACHE_HEADER *cache, int ntfs_invalidate_cache( struct CACHE_HEADER *cache,
const struct CACHED_GENERIC *item, const struct CACHED_GENERIC *item,
cache_compare compare, int flags); cache_compare compare, int flags );
int ntfs_remove_cache(struct CACHE_HEADER *cache, int ntfs_remove_cache( struct CACHE_HEADER *cache,
struct CACHED_GENERIC *item, int flags); struct CACHED_GENERIC *item, int flags );
void ntfs_create_lru_caches(ntfs_volume *vol); void ntfs_create_lru_caches( ntfs_volume *vol );
void ntfs_free_lru_caches(ntfs_volume *vol); void ntfs_free_lru_caches( ntfs_volume *vol );
#endif /* _NTFS_CACHE_H_ */ #endif /* _NTFS_CACHE_H_ */

View File

@ -45,330 +45,365 @@
#define CACHE_FREE UINT_MAX #define CACHE_FREE UINT_MAX
NTFS_CACHE* _NTFS_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize) { NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize )
NTFS_CACHE* cache; {
unsigned int i; NTFS_CACHE* cache;
NTFS_CACHE_ENTRY* cacheEntries; unsigned int i;
NTFS_CACHE_ENTRY* cacheEntries;
if(numberOfPages==0 || sectorsPerPage==0) return NULL; if ( numberOfPages == 0 || sectorsPerPage == 0 ) return NULL;
if (numberOfPages < 4) { if ( numberOfPages < 4 )
numberOfPages = 4; {
} numberOfPages = 4;
}
if (sectorsPerPage < 32) { if ( sectorsPerPage < 32 )
sectorsPerPage = 32; {
} sectorsPerPage = 32;
}
cache = (NTFS_CACHE*) ntfs_alloc (sizeof(NTFS_CACHE)); cache = ( NTFS_CACHE* ) ntfs_alloc ( sizeof( NTFS_CACHE ) );
if (cache == NULL) { if ( cache == NULL )
return NULL; {
} return NULL;
}
cache->disc = discInterface; cache->disc = discInterface;
cache->endOfPartition = endOfPartition; cache->endOfPartition = endOfPartition;
cache->numberOfPages = numberOfPages; cache->numberOfPages = numberOfPages;
cache->sectorsPerPage = sectorsPerPage; cache->sectorsPerPage = sectorsPerPage;
cache->sectorSize = sectorSize; cache->sectorSize = sectorSize;
cacheEntries = (NTFS_CACHE_ENTRY*) ntfs_alloc ( sizeof(NTFS_CACHE_ENTRY) * numberOfPages); cacheEntries = ( NTFS_CACHE_ENTRY* ) ntfs_alloc ( sizeof( NTFS_CACHE_ENTRY ) * numberOfPages );
if (cacheEntries == NULL) { if ( cacheEntries == NULL )
ntfs_free (cache); {
return NULL; ntfs_free ( cache );
} return NULL;
}
for (i = 0; i < numberOfPages; i++) { for ( i = 0; i < numberOfPages; i++ )
cacheEntries[i].sector = CACHE_FREE; {
cacheEntries[i].count = 0; cacheEntries[i].sector = CACHE_FREE;
cacheEntries[i].last_access = 0; cacheEntries[i].count = 0;
cacheEntries[i].dirty = false; cacheEntries[i].last_access = 0;
cacheEntries[i].cache = (uint8_t*) ntfs_align ( sectorsPerPage * cache->sectorSize ); cacheEntries[i].dirty = false;
} cacheEntries[i].cache = ( uint8_t* ) ntfs_align ( sectorsPerPage * cache->sectorSize );
}
cache->cacheEntries = cacheEntries; cache->cacheEntries = cacheEntries;
return cache; return cache;
} }
void _NTFS_cache_destructor (NTFS_CACHE* cache) { void _NTFS_cache_destructor ( NTFS_CACHE* cache )
unsigned int i; {
unsigned int i;
if(cache==NULL) return; if ( cache == NULL ) return;
// Clear out cache before destroying it // Clear out cache before destroying it
_NTFS_cache_flush(cache); _NTFS_cache_flush( cache );
// Free memory in reverse allocation order // Free memory in reverse allocation order
for (i = 0; i < cache->numberOfPages; i++) { for ( i = 0; i < cache->numberOfPages; i++ )
ntfs_free (cache->cacheEntries[i].cache); {
} ntfs_free ( cache->cacheEntries[i].cache );
ntfs_free (cache->cacheEntries); }
ntfs_free (cache); ntfs_free ( cache->cacheEntries );
ntfs_free ( cache );
} }
static u32 accessCounter = 0; static u32 accessCounter = 0;
static u32 accessTime(){ static u32 accessTime()
accessCounter++;
return accessCounter;
}
static NTFS_CACHE_ENTRY* _NTFS_cache_getPage(NTFS_CACHE *cache,sec_t sector)
{ {
unsigned int i; accessCounter++;
NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries; return accessCounter;
unsigned int numberOfPages = cache->numberOfPages;
unsigned int sectorsPerPage = cache->sectorsPerPage;
bool foundFree = false;
unsigned int oldUsed = 0;
unsigned int oldAccess = UINT_MAX;
for(i=0;i<numberOfPages;i++) {
if(sector>=cacheEntries[i].sector && sector<(cacheEntries[i].sector + cacheEntries[i].count)) {
cacheEntries[i].last_access = accessTime();
return &(cacheEntries[i]);
}
if(foundFree==false && (cacheEntries[i].sector==CACHE_FREE || cacheEntries[i].last_access<oldAccess)) {
if(cacheEntries[i].sector==CACHE_FREE) foundFree = true;
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
}
if(foundFree==false && cacheEntries[oldUsed].dirty==true) {
if(!cache->disc->writeSectors(cacheEntries[oldUsed].sector,cacheEntries[oldUsed].count,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].dirty = false;
}
sector = (sector/sectorsPerPage)*sectorsPerPage; // align base sector to page size
sec_t next_page = sector + sectorsPerPage;
if(next_page > cache->endOfPartition) next_page = cache->endOfPartition;
if(!cache->disc->readSectors(sector,next_page-sector,cacheEntries[oldUsed].cache)) return NULL;
cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = next_page-sector;
cacheEntries[oldUsed].last_access = accessTime();
return &(cacheEntries[oldUsed]);
} }
static NTFS_CACHE_ENTRY* _NTFS_cache_findPage(NTFS_CACHE *cache, sec_t sector, sec_t count) { static NTFS_CACHE_ENTRY* _NTFS_cache_getPage( NTFS_CACHE *cache, sec_t sector )
unsigned int i;
NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
NTFS_CACHE_ENTRY *entry = NULL;
sec_t lowest = UINT_MAX;
for(i=0;i<numberOfPages;i++) {
if (cacheEntries[i].sector != CACHE_FREE) {
bool intersect;
if (sector > cacheEntries[i].sector) {
intersect = sector - cacheEntries[i].sector < cacheEntries[i].count;
} else {
intersect = cacheEntries[i].sector - sector < count;
}
if ( intersect && (cacheEntries[i].sector < lowest)) {
lowest = cacheEntries[i].sector;
entry = &cacheEntries[i];
}
}
}
return entry;
}
bool _NTFS_cache_readSectors(NTFS_CACHE *cache,sec_t sector,sec_t numSectors,void *buffer)
{ {
sec_t sec; unsigned int i;
sec_t secs_to_read; NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries;
NTFS_CACHE_ENTRY *entry; unsigned int numberOfPages = cache->numberOfPages;
uint8_t *dest = buffer; unsigned int sectorsPerPage = cache->sectorsPerPage;
while(numSectors>0) { bool foundFree = false;
entry = _NTFS_cache_getPage(cache,sector); unsigned int oldUsed = 0;
if(entry==NULL) return false; unsigned int oldAccess = UINT_MAX;
sec = sector - entry->sector; for ( i = 0; i < numberOfPages; i++ )
secs_to_read = entry->count - sec; {
if(secs_to_read>numSectors) secs_to_read = numSectors; if ( sector >= cacheEntries[i].sector && sector < ( cacheEntries[i].sector + cacheEntries[i].count ) )
{
cacheEntries[i].last_access = accessTime();
return &( cacheEntries[i] );
}
memcpy(dest,entry->cache + (sec*cache->sectorSize),(secs_to_read*cache->sectorSize)); if ( foundFree == false && ( cacheEntries[i].sector == CACHE_FREE || cacheEntries[i].last_access < oldAccess ) )
{
if ( cacheEntries[i].sector == CACHE_FREE ) foundFree = true;
oldUsed = i;
oldAccess = cacheEntries[i].last_access;
}
}
dest += (secs_to_read*cache->sectorSize); if ( foundFree == false && cacheEntries[oldUsed].dirty == true )
sector += secs_to_read; {
numSectors -= secs_to_read; if ( !cache->disc->writeSectors( cacheEntries[oldUsed].sector, cacheEntries[oldUsed].count, cacheEntries[oldUsed].cache ) ) return NULL;
} cacheEntries[oldUsed].dirty = false;
}
sector = ( sector / sectorsPerPage ) * sectorsPerPage; // align base sector to page size
sec_t next_page = sector + sectorsPerPage;
if ( next_page > cache->endOfPartition ) next_page = cache->endOfPartition;
return true; if ( !cache->disc->readSectors( sector, next_page - sector, cacheEntries[oldUsed].cache ) ) return NULL;
cacheEntries[oldUsed].sector = sector;
cacheEntries[oldUsed].count = next_page - sector;
cacheEntries[oldUsed].last_access = accessTime();
return &( cacheEntries[oldUsed] );
}
static NTFS_CACHE_ENTRY* _NTFS_cache_findPage( NTFS_CACHE *cache, sec_t sector, sec_t count )
{
unsigned int i;
NTFS_CACHE_ENTRY* cacheEntries = cache->cacheEntries;
unsigned int numberOfPages = cache->numberOfPages;
NTFS_CACHE_ENTRY *entry = NULL;
sec_t lowest = UINT_MAX;
for ( i = 0; i < numberOfPages; i++ )
{
if ( cacheEntries[i].sector != CACHE_FREE )
{
bool intersect;
if ( sector > cacheEntries[i].sector )
{
intersect = sector - cacheEntries[i].sector < cacheEntries[i].count;
}
else
{
intersect = cacheEntries[i].sector - sector < count;
}
if ( intersect && ( cacheEntries[i].sector < lowest ) )
{
lowest = cacheEntries[i].sector;
entry = &cacheEntries[i];
}
}
}
return entry;
}
bool _NTFS_cache_readSectors( NTFS_CACHE *cache, sec_t sector, sec_t numSectors, void *buffer )
{
sec_t sec;
sec_t secs_to_read;
NTFS_CACHE_ENTRY *entry;
uint8_t *dest = buffer;
while ( numSectors > 0 )
{
entry = _NTFS_cache_getPage( cache, sector );
if ( entry == NULL ) return false;
sec = sector - entry->sector;
secs_to_read = entry->count - sec;
if ( secs_to_read > numSectors ) secs_to_read = numSectors;
memcpy( dest, entry->cache + ( sec*cache->sectorSize ), ( secs_to_read*cache->sectorSize ) );
dest += ( secs_to_read * cache->sectorSize );
sector += secs_to_read;
numSectors -= secs_to_read;
}
return true;
} }
/* /*
Reads some data from a cache page, determined by the sector number Reads some data from a cache page, determined by the sector number
*/ */
bool _NTFS_cache_readPartialSector (NTFS_CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size) bool _NTFS_cache_readPartialSector ( NTFS_CACHE* cache, void* buffer, sec_t sector, unsigned int offset, size_t size )
{ {
sec_t sec; sec_t sec;
NTFS_CACHE_ENTRY *entry; NTFS_CACHE_ENTRY *entry;
if (offset + size > cache->sectorSize) return false; if ( offset + size > cache->sectorSize ) return false;
entry = _NTFS_cache_getPage(cache,sector); entry = _NTFS_cache_getPage( cache, sector );
if(entry==NULL) return false; if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
memcpy(buffer,entry->cache + ((sec*cache->sectorSize) + offset),size); memcpy( buffer, entry->cache + ( ( sec*cache->sectorSize ) + offset ), size );
return true; return true;
} }
bool _NTFS_cache_readLittleEndianValue (NTFS_CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes) { bool _NTFS_cache_readLittleEndianValue ( NTFS_CACHE* cache, uint32_t *value, sec_t sector, unsigned int offset, int num_bytes )
uint8_t buf[4]; {
if (!_NTFS_cache_readPartialSector(cache, buf, sector, offset, num_bytes)) return false; uint8_t buf[4];
if ( !_NTFS_cache_readPartialSector( cache, buf, sector, offset, num_bytes ) ) return false;
switch(num_bytes) { switch ( num_bytes )
case 1: *value = buf[0]; break; {
case 2: *value = u8array_to_u16(buf,0); break; case 1: *value = buf[0]; break;
case 4: *value = u8array_to_u32(buf,0); break; case 2: *value = u8array_to_u16( buf, 0 ); break;
default: return false; case 4: *value = u8array_to_u32( buf, 0 ); break;
} default: return false;
return true; }
return true;
} }
/* /*
Writes some data to a cache page, making sure it is loaded into memory first. Writes some data to a cache page, making sure it is loaded into memory first.
*/ */
bool _NTFS_cache_writePartialSector (NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) bool _NTFS_cache_writePartialSector ( NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size )
{ {
sec_t sec; sec_t sec;
NTFS_CACHE_ENTRY *entry; NTFS_CACHE_ENTRY *entry;
if (offset + size > cache->sectorSize) return false; if ( offset + size > cache->sectorSize ) return false;
entry = _NTFS_cache_getPage(cache,sector); entry = _NTFS_cache_getPage( cache, sector );
if(entry==NULL) return false; if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
memcpy(entry->cache + ((sec*cache->sectorSize) + offset),buffer,size); memcpy( entry->cache + ( ( sec*cache->sectorSize ) + offset ), buffer, size );
entry->dirty = true; entry->dirty = true;
return true; return true;
} }
bool _NTFS_cache_writeLittleEndianValue (NTFS_CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size) { bool _NTFS_cache_writeLittleEndianValue ( NTFS_CACHE* cache, const uint32_t value, sec_t sector, unsigned int offset, int size )
uint8_t buf[4] = {0, 0, 0, 0}; {
uint8_t buf[4] = {0, 0, 0, 0};
switch(size) { switch ( size )
case 1: buf[0] = value; break; {
case 2: u16_to_u8array(buf, 0, value); break; case 1: buf[0] = value; break;
case 4: u32_to_u8array(buf, 0, value); break; case 2: u16_to_u8array( buf, 0, value ); break;
default: return false; case 4: u32_to_u8array( buf, 0, value ); break;
} default: return false;
}
return _NTFS_cache_writePartialSector(cache, buf, sector, offset, size); return _NTFS_cache_writePartialSector( cache, buf, sector, offset, size );
} }
/* /*
Writes some data to a cache page, zeroing out the page first Writes some data to a cache page, zeroing out the page first
*/ */
bool _NTFS_cache_eraseWritePartialSector (NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size) bool _NTFS_cache_eraseWritePartialSector ( NTFS_CACHE* cache, const void* buffer, sec_t sector, unsigned int offset, size_t size )
{ {
sec_t sec; sec_t sec;
NTFS_CACHE_ENTRY *entry; NTFS_CACHE_ENTRY *entry;
if (offset + size > cache->sectorSize) return false; if ( offset + size > cache->sectorSize ) return false;
entry = _NTFS_cache_getPage(cache,sector); entry = _NTFS_cache_getPage( cache, sector );
if(entry==NULL) return false; if ( entry == NULL ) return false;
sec = sector - entry->sector; sec = sector - entry->sector;
memset(entry->cache + (sec*cache->sectorSize),0,cache->sectorSize); memset( entry->cache + ( sec*cache->sectorSize ), 0, cache->sectorSize );
memcpy(entry->cache + ((sec*cache->sectorSize) + offset),buffer,size); memcpy( entry->cache + ( ( sec*cache->sectorSize ) + offset ), buffer, size );
entry->dirty = true; entry->dirty = true;
return true; return true;
} }
bool _NTFS_cache_writeSectors (NTFS_CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer) bool _NTFS_cache_writeSectors ( NTFS_CACHE* cache, sec_t sector, sec_t numSectors, const void* buffer )
{ {
sec_t sec; sec_t sec;
sec_t secs_to_write; sec_t secs_to_write;
NTFS_CACHE_ENTRY* entry; NTFS_CACHE_ENTRY* entry;
const uint8_t *src = buffer; const uint8_t *src = buffer;
while(numSectors>0) while ( numSectors > 0 )
{ {
entry = _NTFS_cache_findPage(cache,sector,numSectors); entry = _NTFS_cache_findPage( cache, sector, numSectors );
if(entry!=NULL) { if ( entry != NULL )
{
if ( entry->sector > sector) { if ( entry->sector > sector )
{
secs_to_write = entry->sector - sector; secs_to_write = entry->sector - sector;
cache->disc->writeSectors(sector,secs_to_write,src); cache->disc->writeSectors( sector, secs_to_write, src );
src += (secs_to_write*cache->sectorSize); src += ( secs_to_write * cache->sectorSize );
sector += secs_to_write; sector += secs_to_write;
numSectors -= secs_to_write; numSectors -= secs_to_write;
} }
sec = sector - entry->sector; sec = sector - entry->sector;
secs_to_write = entry->count - sec; secs_to_write = entry->count - sec;
if(secs_to_write>numSectors) secs_to_write = numSectors; if ( secs_to_write > numSectors ) secs_to_write = numSectors;
memcpy(entry->cache + (sec*cache->sectorSize),src,(secs_to_write*cache->sectorSize)); memcpy( entry->cache + ( sec*cache->sectorSize ), src, ( secs_to_write*cache->sectorSize ) );
src += (secs_to_write*cache->sectorSize); src += ( secs_to_write * cache->sectorSize );
sector += secs_to_write; sector += secs_to_write;
numSectors -= secs_to_write; numSectors -= secs_to_write;
entry->dirty = true; entry->dirty = true;
} else { }
cache->disc->writeSectors(sector,numSectors,src); else
numSectors=0; {
} cache->disc->writeSectors( sector, numSectors, src );
} numSectors = 0;
return true; }
}
return true;
} }
/* /*
Flushes all dirty pages to disc, clearing the dirty flag. Flushes all dirty pages to disc, clearing the dirty flag.
*/ */
bool _NTFS_cache_flush (NTFS_CACHE* cache) { bool _NTFS_cache_flush ( NTFS_CACHE* cache )
unsigned int i; {
if(cache==NULL) return true; unsigned int i;
if ( cache == NULL ) return true;
for (i = 0; i < cache->numberOfPages; i++) { for ( i = 0; i < cache->numberOfPages; i++ )
if (cache->cacheEntries[i].dirty) { {
if (!cache->disc->writeSectors (cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache)) { if ( cache->cacheEntries[i].dirty )
return false; {
} if ( !cache->disc->writeSectors ( cache->cacheEntries[i].sector, cache->cacheEntries[i].count, cache->cacheEntries[i].cache ) )
} {
cache->cacheEntries[i].dirty = false; return false;
} }
}
cache->cacheEntries[i].dirty = false;
}
return true; return true;
} }
void _NTFS_cache_invalidate (NTFS_CACHE* cache) { void _NTFS_cache_invalidate ( NTFS_CACHE* cache )
unsigned int i; {
if(cache==NULL) unsigned int i;
if ( cache == NULL )
return; return;
_NTFS_cache_flush(cache); _NTFS_cache_flush( cache );
for (i = 0; i < cache->numberOfPages; i++) { for ( i = 0; i < cache->numberOfPages; i++ )
cache->cacheEntries[i].sector = CACHE_FREE; {
cache->cacheEntries[i].last_access = 0; cache->cacheEntries[i].sector = CACHE_FREE;
cache->cacheEntries[i].count = 0; cache->cacheEntries[i].last_access = 0;
cache->cacheEntries[i].dirty = false; cache->cacheEntries[i].count = 0;
} cache->cacheEntries[i].dirty = false;
}
} }

View File

@ -46,21 +46,23 @@
#include <ogc/disc_io.h> #include <ogc/disc_io.h>
#include <gccore.h> #include <gccore.h>
typedef struct { typedef struct
sec_t sector; {
unsigned int count; sec_t sector;
u64 last_access; unsigned int count;
bool dirty; u64 last_access;
u8* cache; bool dirty;
u8* cache;
} NTFS_CACHE_ENTRY; } NTFS_CACHE_ENTRY;
typedef struct { typedef struct
const DISC_INTERFACE* disc; {
sec_t endOfPartition; const DISC_INTERFACE* disc;
unsigned int numberOfPages; sec_t endOfPartition;
unsigned int sectorsPerPage; unsigned int numberOfPages;
sec_t sectorSize; unsigned int sectorsPerPage;
NTFS_CACHE_ENTRY* cacheEntries; sec_t sectorSize;
NTFS_CACHE_ENTRY* cacheEntries;
} NTFS_CACHE; } NTFS_CACHE;
/* /*
@ -99,37 +101,37 @@ Precondition: offset + size <= BYTES_PER_READ
/* /*
Read several sectors from the NTFS_CACHE Read several sectors from the NTFS_CACHE
*/ */
bool _NTFS_cache_readSectors (NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, void* buffer); bool _NTFS_cache_readSectors ( NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, void* buffer );
/* /*
Read a full sector from the NTFS_CACHE Read a full sector from the NTFS_CACHE
*/ */
//static inline bool _NTFS_cache_readSector (NTFS_CACHE* NTFS_CACHE, void* buffer, sec_t sector) { //static inline bool _NTFS_cache_readSector (NTFS_CACHE* NTFS_CACHE, void* buffer, sec_t sector) {
// return _NTFS_cache_readPartialSector (NTFS_CACHE, buffer, sector, 0, BYTES_PER_READ); // return _NTFS_cache_readPartialSector (NTFS_CACHE, buffer, sector, 0, BYTES_PER_READ);
//} //}
/* /*
Write a full sector to the NTFS_CACHE Write a full sector to the NTFS_CACHE
*/ */
//static inline bool _NTFS_cache_writeSector (NTFS_CACHE* NTFS_CACHE, const void* buffer, sec_t sector) { //static inline bool _NTFS_cache_writeSector (NTFS_CACHE* NTFS_CACHE, const void* buffer, sec_t sector) {
// return _NTFS_cache_writePartialSector (NTFS_CACHE, buffer, sector, 0, BYTES_PER_READ); // return _NTFS_cache_writePartialSector (NTFS_CACHE, buffer, sector, 0, BYTES_PER_READ);
//} //}
bool _NTFS_cache_writeSectors (NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, const void* buffer); bool _NTFS_cache_writeSectors ( NTFS_CACHE* NTFS_CACHE, sec_t sector, sec_t numSectors, const void* buffer );
/* /*
Write any dirty sectors back to disc and clear out the contents of the NTFS_CACHE Write any dirty sectors back to disc and clear out the contents of the NTFS_CACHE
*/ */
bool _NTFS_cache_flush (NTFS_CACHE* NTFS_CACHE); bool _NTFS_cache_flush ( NTFS_CACHE* NTFS_CACHE );
/* /*
Clear out the contents of the NTFS_CACHE without writing any dirty sectors first Clear out the contents of the NTFS_CACHE without writing any dirty sectors first
*/ */
void _NTFS_cache_invalidate (NTFS_CACHE* NTFS_CACHE); void _NTFS_cache_invalidate ( NTFS_CACHE* NTFS_CACHE );
NTFS_CACHE* _NTFS_cache_constructor (unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize); NTFS_CACHE* _NTFS_cache_constructor ( unsigned int numberOfPages, unsigned int sectorsPerPage, const DISC_INTERFACE* discInterface, sec_t endOfPartition, sec_t sectorSize );
void _NTFS_cache_destructor (NTFS_CACHE* NTFS_CACHE); void _NTFS_cache_destructor ( NTFS_CACHE* NTFS_CACHE );
#endif // _CACHE_H #endif // _CACHE_H

View File

@ -52,22 +52,23 @@
* *
* Returns: * Returns:
*/ */
static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)), static int ntfs_collate_binary( ntfs_volume *vol __attribute__( ( unused ) ),
const void *data1, const int data1_len, const void *data1, const int data1_len,
const void *data2, const int data2_len) const void *data2, const int data2_len )
{ {
int rc; int rc;
ntfs_log_trace("Entering.\n"); ntfs_log_trace( "Entering.\n" );
rc = memcmp(data1, data2, min(data1_len, data2_len)); rc = memcmp( data1, data2, min( data1_len, data2_len ) );
if (!rc && (data1_len != data2_len)) { if ( !rc && ( data1_len != data2_len ) )
if (data1_len < data2_len) {
rc = -1; if ( data1_len < data2_len )
else rc = -1;
rc = 1; else
} rc = 1;
ntfs_log_trace("Done, returning %i.\n", rc); }
return rc; ntfs_log_trace( "Done, returning %i.\n", rc );
return rc;
} }
/** /**
@ -82,30 +83,32 @@ static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)),
* *
* Returns: * Returns:
*/ */
static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), static int ntfs_collate_ntofs_ulong( ntfs_volume *vol __attribute__( ( unused ) ),
const void *data1, const int data1_len, const void *data1, const int data1_len,
const void *data2, const int data2_len) const void *data2, const int data2_len )
{ {
int rc; int rc;
u32 d1, d2; u32 d1, d2;
ntfs_log_trace("Entering.\n"); ntfs_log_trace( "Entering.\n" );
if (data1_len != data2_len || data1_len != 4) { if ( data1_len != data2_len || data1_len != 4 )
ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); {
return NTFS_COLLATION_ERROR; ntfs_log_error( "data1_len or/and data2_len not equal to 4.\n" );
} return NTFS_COLLATION_ERROR;
d1 = le32_to_cpup(data1); }
d2 = le32_to_cpup(data2); d1 = le32_to_cpup( data1 );
if (d1 < d2) d2 = le32_to_cpup( data2 );
rc = -1; if ( d1 < d2 )
else { rc = -1;
if (d1 == d2) else
rc = 0; {
else if ( d1 == d2 )
rc = 1; rc = 0;
} else
ntfs_log_trace("Done, returning %i.\n", rc); rc = 1;
return rc; }
ntfs_log_trace( "Done, returning %i.\n", rc );
return rc;
} }
/** /**
@ -114,39 +117,43 @@ static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)),
* Returns: -1, 0 or 1 depending of how the arrays compare * Returns: -1, 0 or 1 depending of how the arrays compare
*/ */
static int ntfs_collate_ntofs_ulongs(ntfs_volume *vol __attribute__((unused)), static int ntfs_collate_ntofs_ulongs( ntfs_volume *vol __attribute__( ( unused ) ),
const void *data1, const int data1_len, const void *data1, const int data1_len,
const void *data2, const int data2_len) const void *data2, const int data2_len )
{ {
int rc; int rc;
int len; int len;
const le32 *p1, *p2; const le32 *p1, *p2;
u32 d1, d2; u32 d1, d2;
ntfs_log_trace("Entering.\n"); ntfs_log_trace( "Entering.\n" );
if ((data1_len != data2_len) || (data1_len <= 0) || (data1_len & 3)) { if ( ( data1_len != data2_len ) || ( data1_len <= 0 ) || ( data1_len & 3 ) )
ntfs_log_error("data1_len or data2_len not valid\n"); {
return NTFS_COLLATION_ERROR; ntfs_log_error( "data1_len or data2_len not valid\n" );
} return NTFS_COLLATION_ERROR;
p1 = (const le32*)data1; }
p2 = (const le32*)data2; p1 = ( const le32* )data1;
len = data1_len; p2 = ( const le32* )data2;
do { len = data1_len;
d1 = le32_to_cpup(p1); do
p1++; {
d2 = le32_to_cpup(p2); d1 = le32_to_cpup( p1 );
p2++; p1++;
} while ((d1 == d2) && ((len -= 4) > 0)); d2 = le32_to_cpup( p2 );
if (d1 < d2) p2++;
rc = -1; }
else { while ( ( d1 == d2 ) && ( ( len -= 4 ) > 0 ) );
if (d1 == d2) if ( d1 < d2 )
rc = 0; rc = -1;
else else
rc = 1; {
} if ( d1 == d2 )
ntfs_log_trace("Done, returning %i.\n", rc); rc = 0;
return rc; else
rc = 1;
}
ntfs_log_trace( "Done, returning %i.\n", rc );
return rc;
} }
/** /**
@ -162,45 +169,49 @@ static int ntfs_collate_ntofs_ulongs(ntfs_volume *vol __attribute__((unused)),
* *
* Returns: -1, 0 or 1 depending of how the keys compare * Returns: -1, 0 or 1 depending of how the keys compare
*/ */
static int ntfs_collate_ntofs_security_hash(ntfs_volume *vol __attribute__((unused)), static int ntfs_collate_ntofs_security_hash( ntfs_volume *vol __attribute__( ( unused ) ),
const void *data1, const int data1_len, const void *data1, const int data1_len,
const void *data2, const int data2_len) const void *data2, const int data2_len )
{ {
int rc; int rc;
u32 d1, d2; u32 d1, d2;
const le32 *p1, *p2; const le32 *p1, *p2;
ntfs_log_trace("Entering.\n"); ntfs_log_trace( "Entering.\n" );
if (data1_len != data2_len || data1_len != 8) { if ( data1_len != data2_len || data1_len != 8 )
ntfs_log_error("data1_len or/and data2_len not equal to 8.\n"); {
return NTFS_COLLATION_ERROR; ntfs_log_error( "data1_len or/and data2_len not equal to 8.\n" );
} return NTFS_COLLATION_ERROR;
p1 = (const le32*)data1; }
p2 = (const le32*)data2; p1 = ( const le32* )data1;
d1 = le32_to_cpup(p1); p2 = ( const le32* )data2;
d2 = le32_to_cpup(p2); d1 = le32_to_cpup( p1 );
if (d1 < d2) d2 = le32_to_cpup( p2 );
rc = -1; if ( d1 < d2 )
else { rc = -1;
if (d1 > d2) else
rc = 1; {
else { if ( d1 > d2 )
p1++; rc = 1;
p2++; else
d1 = le32_to_cpup(p1); {
d2 = le32_to_cpup(p2); p1++;
if (d1 < d2) p2++;
rc = -1; d1 = le32_to_cpup( p1 );
else { d2 = le32_to_cpup( p2 );
if (d1 > d2) if ( d1 < d2 )
rc = 1; rc = -1;
else else
rc = 0; {
} if ( d1 > d2 )
} rc = 1;
} else
ntfs_log_trace("Done, returning %i.\n", rc); rc = 0;
return rc; }
}
}
ntfs_log_trace( "Done, returning %i.\n", rc );
return rc;
} }
/** /**
@ -215,57 +226,58 @@ static int ntfs_collate_ntofs_security_hash(ntfs_volume *vol __attribute__((unus
* *
* Returns: * Returns:
*/ */
static int ntfs_collate_file_name(ntfs_volume *vol, static int ntfs_collate_file_name( ntfs_volume *vol,
const void *data1, const int data1_len __attribute__((unused)), const void *data1, const int data1_len __attribute__( ( unused ) ),
const void *data2, const int data2_len __attribute__((unused))) const void *data2, const int data2_len __attribute__( ( unused ) ) )
{ {
const FILE_NAME_ATTR *file_name_attr1; const FILE_NAME_ATTR *file_name_attr1;
const FILE_NAME_ATTR *file_name_attr2; const FILE_NAME_ATTR *file_name_attr2;
int rc; int rc;
ntfs_log_trace("Entering.\n"); ntfs_log_trace( "Entering.\n" );
file_name_attr1 = (const FILE_NAME_ATTR*)data1; file_name_attr1 = ( const FILE_NAME_ATTR* )data1;
file_name_attr2 = (const FILE_NAME_ATTR*)data2; file_name_attr2 = ( const FILE_NAME_ATTR* )data2;
rc = ntfs_names_full_collate( rc = ntfs_names_full_collate(
(ntfschar*)&file_name_attr1->file_name, ( ntfschar* ) & file_name_attr1->file_name,
file_name_attr1->file_name_length, file_name_attr1->file_name_length,
(ntfschar*)&file_name_attr2->file_name, ( ntfschar* ) & file_name_attr2->file_name,
file_name_attr2->file_name_length, file_name_attr2->file_name_length,
CASE_SENSITIVE, vol->upcase, vol->upcase_len); CASE_SENSITIVE, vol->upcase, vol->upcase_len );
ntfs_log_trace("Done, returning %i.\n", rc); ntfs_log_trace( "Done, returning %i.\n", rc );
return rc; return rc;
} }
/* /*
* Get a pointer to appropriate collation function. * Get a pointer to appropriate collation function.
* *
* Returns NULL if the needed function is not implemented * Returns NULL if the needed function is not implemented
*/ */
COLLATE ntfs_get_collate_function(COLLATION_RULES cr) COLLATE ntfs_get_collate_function( COLLATION_RULES cr )
{ {
COLLATE collate; COLLATE collate;
switch (cr) { switch ( cr )
case COLLATION_BINARY : {
collate = ntfs_collate_binary; case COLLATION_BINARY :
break; collate = ntfs_collate_binary;
case COLLATION_FILE_NAME : break;
collate = ntfs_collate_file_name; case COLLATION_FILE_NAME :
break; collate = ntfs_collate_file_name;
case COLLATION_NTOFS_SECURITY_HASH : break;
collate = ntfs_collate_ntofs_security_hash; case COLLATION_NTOFS_SECURITY_HASH :
break; collate = ntfs_collate_ntofs_security_hash;
case COLLATION_NTOFS_ULONG : break;
collate = ntfs_collate_ntofs_ulong; case COLLATION_NTOFS_ULONG :
break; collate = ntfs_collate_ntofs_ulong;
case COLLATION_NTOFS_ULONGS : break;
collate = ntfs_collate_ntofs_ulongs; case COLLATION_NTOFS_ULONGS :
break; collate = ntfs_collate_ntofs_ulongs;
default : break;
errno = EOPNOTSUPP; default :
collate = (COLLATE)NULL; errno = EOPNOTSUPP;
break; collate = ( COLLATE )NULL;
} break;
return (collate); }
return ( collate );
} }

View File

@ -29,6 +29,6 @@
#define NTFS_COLLATION_ERROR -2 #define NTFS_COLLATION_ERROR -2
extern COLLATE ntfs_get_collate_function(COLLATION_RULES); extern COLLATE ntfs_get_collate_function( COLLATION_RULES );
#endif /* _NTFS_COLLATE_H */ #endif /* _NTFS_COLLATE_H */

View File

@ -35,33 +35,38 @@
* *
* Returns: * Returns:
*/ */
int ffs(int x) int ffs( int x )
{ {
int r = 1; int r = 1;
if (!x) if ( !x )
return 0; return 0;
if (!(x & 0xffff)) { if ( !( x & 0xffff ) )
x >>= 16; {
r += 16; x >>= 16;
} r += 16;
if (!(x & 0xff)) { }
x >>= 8; if ( !( x & 0xff ) )
r += 8; {
} x >>= 8;
if (!(x & 0xf)) { r += 8;
x >>= 4; }
r += 4; if ( !( x & 0xf ) )
} {
if (!(x & 3)) { x >>= 4;
x >>= 2; r += 4;
r += 2; }
} if ( !( x & 3 ) )
if (!(x & 1)) { {
x >>= 1; x >>= 2;
r += 1; r += 2;
} }
return r; if ( !( x & 1 ) )
{
x >>= 1;
r += 1;
}
return r;
} }
#endif /* HAVE_FFS */ #endif /* HAVE_FFS */
@ -82,7 +87,7 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
/* /*
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -94,8 +99,8 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by the University of * This product includes software developed by the University of
* California, Berkeley and its contributors. * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors * 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -120,34 +125,37 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
#include <unistd.h> #include <unistd.h>
#endif #endif
int daemon(int nochdir, int noclose) { int daemon( int nochdir, int noclose )
int fd; {
int fd;
switch (fork()) { switch ( fork() )
case -1: {
return (-1); case -1:
case 0: return ( -1 );
break; case 0:
default: break;
_exit(0); default:
} _exit( 0 );
}
if (setsid() == -1) if ( setsid() == -1 )
return (-1); return ( -1 );
if (!nochdir) if ( !nochdir )
(void)chdir("/"); ( void )chdir( "/" );
if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) { if ( !noclose && ( fd = open( "/dev/null", O_RDWR, 0 ) ) != -1 )
(void)dup2(fd, 0); {
(void)dup2(fd, 1); ( void )dup2( fd, 0 );
(void)dup2(fd, 2); ( void )dup2( fd, 1 );
if (fd > 2) ( void )dup2( fd, 2 );
(void)close (fd); if ( fd > 2 )
} ( void )close ( fd );
return (0); }
return ( 0 );
} }
/* /*
* End: src/lib/libresolv2/common/bsd/daemon.c * End: src/lib/libresolv2/common/bsd/daemon.c
*************************************************************/ *************************************************************/
#endif /* HAVE_DAEMON */ #endif /* HAVE_DAEMON */
@ -169,7 +177,7 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
/* /*
* Copyright (c) 1990, 1993 * Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -181,8 +189,8 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software * 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement: * must display the following acknowledgement:
* This product includes software developed by the University of * This product includes software developed by the University of
* California, Berkeley and its contributors. * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors * 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
* without specific prior written permission. * without specific prior written permission.
@ -209,7 +217,7 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
/* /*
* Get next token from string *stringp, where tokens are possibly-empty * Get next token from string *stringp, where tokens are possibly-empty
* strings separated by characters from delim. * strings separated by characters from delim.
* *
* Writes NULs into the string at *stringp to end tokens. * Writes NULs into the string at *stringp to end tokens.
* delim need not remain constant from call to call. * delim need not remain constant from call to call.
@ -218,32 +226,37 @@ static const char rcsid[] = "$Id: compat.c,v 1.1.1.1.2.1 2008-08-16 15:17:44 jpa
* *
* If *stringp is NULL, strsep returns NULL. * If *stringp is NULL, strsep returns NULL.
*/ */
char *strsep(char **stringp, const char *delim) { char *strsep( char **stringp, const char *delim )
char *s; {
const char *spanp; char *s;
int c, sc; const char *spanp;
char *tok; int c, sc;
char *tok;
if ((s = *stringp) == NULL) if ( ( s = *stringp ) == NULL )
return (NULL); return ( NULL );
for (tok = s;;) { for ( tok = s;; )
c = *s++; {
spanp = delim; c = *s++;
do { spanp = delim;
if ((sc = *spanp++) == c) { do
if (c == 0) {
s = NULL; if ( ( sc = *spanp++ ) == c )
else {
s[-1] = 0; if ( c == 0 )
*stringp = s; s = NULL;
return (tok); else
} s[-1] = 0;
} while (sc != 0); *stringp = s;
} return ( tok );
/* NOTREACHED */ }
}
while ( sc != 0 );
}
/* NOTREACHED */
} }
/* /*
* End: src/lib/libresolv2/common/bsd/strsep.c * End: src/lib/libresolv2/common/bsd/strsep.c
*************************************************************/ *************************************************************/
#endif /* HAVE_STRSEP */ #endif /* HAVE_STRSEP */

View File

@ -36,38 +36,38 @@
#endif #endif
#ifndef HAVE_FFS #ifndef HAVE_FFS
extern int ffs(int i); extern int ffs( int i );
#endif /* HAVE_FFS */ #endif /* HAVE_FFS */
#ifndef HAVE_DAEMON #ifndef HAVE_DAEMON
extern int daemon(int nochdir, int noclose); extern int daemon( int nochdir, int noclose );
#endif /* HAVE_DAEMON */ #endif /* HAVE_DAEMON */
#ifndef HAVE_STRSEP #ifndef HAVE_STRSEP
extern char *strsep(char **stringp, const char *delim); extern char *strsep( char **stringp, const char *delim );
#endif /* HAVE_STRSEP */ #endif /* HAVE_STRSEP */
#ifdef WINDOWS #ifdef WINDOWS
#define HAVE_STDIO_H /* mimic config.h */ #define HAVE_STDIO_H /* mimic config.h */
#define HAVE_STDARG_H #define HAVE_STDARG_H
#define atoll _atoi64 #define atoll _atoi64
#define fdatasync commit #define fdatasync commit
#define __inline__ inline #define __inline__ inline
#define __attribute__(X) /*nothing*/ #define __attribute__(X) /*nothing*/
#else /* !defined WINDOWS */ #else /* !defined WINDOWS */
#ifndef O_BINARY #ifndef O_BINARY
#define O_BINARY 0 /* unix is binary by default */ #define O_BINARY 0 /* unix is binary by default */
#endif #endif
#ifdef GEKKO #ifdef GEKKO
#include "mem_allocate.h" #include "mem_allocate.h"
#define XATTR_CREATE 1 #define XATTR_CREATE 1
#define XATTR_REPLACE 2 #define XATTR_REPLACE 2
#define MINORBITS 20 #define MINORBITS 20
@ -75,7 +75,7 @@ extern char *strsep(char **stringp, const char *delim);
#define major(dev) ((unsigned int) ((dev) >> MINORBITS)) #define major(dev) ((unsigned int) ((dev) >> MINORBITS))
#define minor(dev) ((unsigned int) ((dev) & MINORMASK)) #define minor(dev) ((unsigned int) ((dev) & MINORMASK))
#define mkdev(ma,mi) (((ma) << MINORBITS) | (mi)) #define mkdev(ma,mi) (((ma) << MINORBITS) | (mi))
#define random rand #define random rand
#endif /* defined GEKKO */ #endif /* defined GEKKO */

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
* compress.h - Exports for compressed attribute handling. * compress.h - Exports for compressed attribute handling.
* Originated from the Linux-NTFS project. * Originated from the Linux-NTFS project.
* *
* Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2004 Anton Altaparmakov
* *
@ -26,16 +26,16 @@
#include "types.h" #include "types.h"
#include "attrib.h" #include "attrib.h"
extern s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, extern s64 ntfs_compressed_attr_pread( ntfs_attr *na, s64 pos, s64 count,
void *b); void *b );
extern s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *brl, s64 wpos, extern s64 ntfs_compressed_pwrite( ntfs_attr *na, runlist_element *brl, s64 wpos,
s64 offs, s64 to_write, s64 rounded, s64 offs, s64 to_write, s64 rounded,
const void *b, int compressed_part, const void *b, int compressed_part,
VCN *update_from); VCN *update_from );
extern int ntfs_compressed_close(ntfs_attr *na, runlist_element *brl, extern int ntfs_compressed_close( ntfs_attr *na, runlist_element *brl,
s64 offs, VCN *update_from); s64 offs, VCN *update_from );
#endif /* defined _NTFS_COMPRESS_H */ #endif /* defined _NTFS_COMPRESS_H */

View File

@ -42,37 +42,43 @@
* *
* Returns: * Returns:
*/ */
void ntfs_debug_runlist_dump(const runlist_element *rl) void ntfs_debug_runlist_dump( const runlist_element *rl )
{ {
int i = 0; int i = 0;
const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED", const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED",
"LCN_ENOENT ", "LCN_EINVAL ", "LCN_ENOENT ", "LCN_EINVAL ",
"LCN_unknown " }; "LCN_unknown "
};
ntfs_log_debug("NTFS-fs DEBUG: Dumping runlist (values in hex):\n"); ntfs_log_debug( "NTFS-fs DEBUG: Dumping runlist (values in hex):\n" );
if (!rl) { if ( !rl )
ntfs_log_debug("Run list not present.\n"); {
return; ntfs_log_debug( "Run list not present.\n" );
} return;
ntfs_log_debug("VCN LCN Run length\n"); }
do { ntfs_log_debug( "VCN LCN Run length\n" );
LCN lcn = (rl + i)->lcn; do
{
LCN lcn = ( rl + i )->lcn;
if (lcn < (LCN)0) { if ( lcn < ( LCN )0 )
int idx = -lcn - 1; {
int idx = -lcn - 1;
if (idx > -LCN_EINVAL - 1) if ( idx > -LCN_EINVAL - 1 )
idx = 4; idx = 4;
ntfs_log_debug("%-16lld %s %-16lld%s\n", ntfs_log_debug( "%-16lld %s %-16lld%s\n",
(long long)rl[i].vcn, lcn_str[idx], ( long long )rl[i].vcn, lcn_str[idx],
(long long)rl[i].length, ( long long )rl[i].length,
rl[i].length ? "" : " (runlist end)"); rl[i].length ? "" : " (runlist end)" );
} else }
ntfs_log_debug("%-16lld %-16lld %-16lld%s\n", else
(long long)rl[i].vcn, (long long)rl[i].lcn, ntfs_log_debug( "%-16lld %-16lld %-16lld%s\n",
(long long)rl[i].length, ( long long )rl[i].vcn, ( long long )rl[i].lcn,
rl[i].length ? "" : " (runlist end)"); ( long long )rl[i].length,
} while (rl[i++].length); rl[i].length ? "" : " (runlist end)" );
}
while ( rl[i++].length );
} }
#endif #endif

View File

@ -31,17 +31,17 @@
struct _runlist_element; struct _runlist_element;
#ifdef DEBUG #ifdef DEBUG
extern void ntfs_debug_runlist_dump(const struct _runlist_element *rl); extern void ntfs_debug_runlist_dump( const struct _runlist_element *rl );
#else #else
static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl __attribute__((unused))) {} static __inline__ void ntfs_debug_runlist_dump( const struct _runlist_element *rl __attribute__( ( unused ) ) ) {}
#endif #endif
#define NTFS_BUG(msg) \ #define NTFS_BUG(msg) \
{ \ { \
int ___i; \ int ___i; \
ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \ ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \
ntfs_log_debug("Forcing segmentation fault!"); \ ntfs_log_debug("Forcing segmentation fault!"); \
___i = ((int*)NULL)[1]; \ ___i = ((int*)NULL)[1]; \
} }
#endif /* defined _NTFS_DEBUG_H */ #endif /* defined _NTFS_DEBUG_H */

File diff suppressed because it is too large Load Diff

View File

@ -36,32 +36,33 @@
* *
* Defined bits for the state field in the ntfs_device structure. * Defined bits for the state field in the ntfs_device structure.
*/ */
typedef enum { typedef enum
ND_Open, /* 1: Device is open. */ {
ND_ReadOnly, /* 1: Device is read-only. */ ND_Open, /* 1: Device is open. */
ND_Dirty, /* 1: Device is dirty, needs sync. */ ND_ReadOnly, /* 1: Device is read-only. */
ND_Block, /* 1: Device is a block device. */ ND_Dirty, /* 1: Device is dirty, needs sync. */
ND_Block, /* 1: Device is a block device. */
} ntfs_device_state_bits; } ntfs_device_state_bits;
#define test_ndev_flag(nd, flag) test_bit(ND_##flag, (nd)->d_state) #define test_ndev_flag(nd, flag) test_bit(ND_##flag, (nd)->d_state)
#define set_ndev_flag(nd, flag) set_bit(ND_##flag, (nd)->d_state) #define set_ndev_flag(nd, flag) set_bit(ND_##flag, (nd)->d_state)
#define clear_ndev_flag(nd, flag) clear_bit(ND_##flag, (nd)->d_state) #define clear_ndev_flag(nd, flag) clear_bit(ND_##flag, (nd)->d_state)
#define NDevOpen(nd) test_ndev_flag(nd, Open) #define NDevOpen(nd) test_ndev_flag(nd, Open)
#define NDevSetOpen(nd) set_ndev_flag(nd, Open) #define NDevSetOpen(nd) set_ndev_flag(nd, Open)
#define NDevClearOpen(nd) clear_ndev_flag(nd, Open) #define NDevClearOpen(nd) clear_ndev_flag(nd, Open)
#define NDevReadOnly(nd) test_ndev_flag(nd, ReadOnly) #define NDevReadOnly(nd) test_ndev_flag(nd, ReadOnly)
#define NDevSetReadOnly(nd) set_ndev_flag(nd, ReadOnly) #define NDevSetReadOnly(nd) set_ndev_flag(nd, ReadOnly)
#define NDevClearReadOnly(nd) clear_ndev_flag(nd, ReadOnly) #define NDevClearReadOnly(nd) clear_ndev_flag(nd, ReadOnly)
#define NDevDirty(nd) test_ndev_flag(nd, Dirty) #define NDevDirty(nd) test_ndev_flag(nd, Dirty)
#define NDevSetDirty(nd) set_ndev_flag(nd, Dirty) #define NDevSetDirty(nd) set_ndev_flag(nd, Dirty)
#define NDevClearDirty(nd) clear_ndev_flag(nd, Dirty) #define NDevClearDirty(nd) clear_ndev_flag(nd, Dirty)
#define NDevBlock(nd) test_ndev_flag(nd, Block) #define NDevBlock(nd) test_ndev_flag(nd, Block)
#define NDevSetBlock(nd) set_ndev_flag(nd, Block) #define NDevSetBlock(nd) set_ndev_flag(nd, Block)
#define NDevClearBlock(nd) clear_ndev_flag(nd, Block) #define NDevClearBlock(nd) clear_ndev_flag(nd, Block)
/** /**
* struct ntfs_device - * struct ntfs_device -
@ -69,12 +70,13 @@ typedef enum {
* The ntfs device structure defining all operations needed to access the low * The ntfs device structure defining all operations needed to access the low
* level device underlying the ntfs volume. * level device underlying the ntfs volume.
*/ */
struct ntfs_device { struct ntfs_device
struct ntfs_device_operations *d_ops; /* Device operations. */ {
unsigned long d_state; /* State of the device. */ struct ntfs_device_operations *d_ops; /* Device operations. */
char *d_name; /* Name of device. */ unsigned long d_state; /* State of the device. */
void *d_private; /* Private data used by the char *d_name; /* Name of device. */
device operations. */ void *d_private; /* Private data used by the
device operations. */
}; };
struct stat; struct stat;
@ -85,44 +87,45 @@ struct stat;
* The ntfs device operations defining all operations that can be performed on * The ntfs device operations defining all operations that can be performed on
* the low level device described by an ntfs device structure. * the low level device described by an ntfs device structure.
*/ */
struct ntfs_device_operations { struct ntfs_device_operations
int (*open)(struct ntfs_device *dev, int flags); {
int (*close)(struct ntfs_device *dev); int ( *open )( struct ntfs_device *dev, int flags );
s64 (*seek)(struct ntfs_device *dev, s64 offset, int whence); int ( *close )( struct ntfs_device *dev );
s64 (*read)(struct ntfs_device *dev, void *buf, s64 count); s64 ( *seek )( struct ntfs_device *dev, s64 offset, int whence );
s64 (*write)(struct ntfs_device *dev, const void *buf, s64 count); s64 ( *read )( struct ntfs_device *dev, void *buf, s64 count );
s64 (*pread)(struct ntfs_device *dev, void *buf, s64 count, s64 offset); s64 ( *write )( struct ntfs_device *dev, const void *buf, s64 count );
s64 (*pwrite)(struct ntfs_device *dev, const void *buf, s64 count, s64 ( *pread )( struct ntfs_device *dev, void *buf, s64 count, s64 offset );
s64 offset); s64 ( *pwrite )( struct ntfs_device *dev, const void *buf, s64 count,
int (*sync)(struct ntfs_device *dev); s64 offset );
int (*stat)(struct ntfs_device *dev, struct stat *buf); int ( *sync )( struct ntfs_device *dev );
int (*ioctl)(struct ntfs_device *dev, int request, void *argp); int ( *stat )( struct ntfs_device *dev, struct stat *buf );
int ( *ioctl )( struct ntfs_device *dev, int request, void *argp );
}; };
extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state, extern struct ntfs_device *ntfs_device_alloc( const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data); struct ntfs_device_operations *dops, void *priv_data );
extern int ntfs_device_free(struct ntfs_device *dev); extern int ntfs_device_free( struct ntfs_device *dev );
extern s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, extern s64 ntfs_pread( struct ntfs_device *dev, const s64 pos, s64 count,
void *b); void *b );
extern s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, extern s64 ntfs_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
const void *b); const void *b );
extern s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count, extern s64 ntfs_mst_pread( struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b); const u32 bksize, void *b );
extern s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, extern s64 ntfs_mst_pwrite( struct ntfs_device *dev, const s64 pos, s64 count,
const u32 bksize, void *b); const u32 bksize, void *b );
extern s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, extern s64 ntfs_cluster_read( const ntfs_volume *vol, const s64 lcn,
const s64 count, void *b); const s64 count, void *b );
extern s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn, extern s64 ntfs_cluster_write( const ntfs_volume *vol, const s64 lcn,
const s64 count, const void *b); const s64 count, const void *b );
extern s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size); extern s64 ntfs_device_size_get( struct ntfs_device *dev, int block_size );
extern s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev); extern s64 ntfs_device_partition_start_sector_get( struct ntfs_device *dev );
extern int ntfs_device_heads_get(struct ntfs_device *dev); extern int ntfs_device_heads_get( struct ntfs_device *dev );
extern int ntfs_device_sectors_per_track_get(struct ntfs_device *dev); extern int ntfs_device_sectors_per_track_get( struct ntfs_device *dev );
extern int ntfs_device_sector_size_get(struct ntfs_device *dev); extern int ntfs_device_sector_size_get( struct ntfs_device *dev );
extern int ntfs_device_block_size_set(struct ntfs_device *dev, int block_size); extern int ntfs_device_block_size_set( struct ntfs_device *dev, int block_size );
#endif /* defined _NTFS_DEVICE_H */ #endif /* defined _NTFS_DEVICE_H */

View File

@ -41,28 +41,29 @@
#else /* __CYGWIN32__ */ #else /* __CYGWIN32__ */
#ifndef HDIO_GETGEO #ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x301 # define HDIO_GETGEO 0x301
/** /**
* struct hd_geometry - * struct hd_geometry -
*/ */
struct hd_geometry { struct hd_geometry
unsigned char heads; {
unsigned char sectors; unsigned char heads;
unsigned short cylinders; unsigned char sectors;
unsigned long start; unsigned short cylinders;
unsigned long start;
}; };
#endif #endif
#ifndef BLKGETSIZE #ifndef BLKGETSIZE
# define BLKGETSIZE 0x1260 # define BLKGETSIZE 0x1260
#endif #endif
#ifndef BLKSSZGET #ifndef BLKSSZGET
# define BLKSSZGET 0x1268 # define BLKSSZGET 0x1268
#endif #endif
#ifndef BLKGETSIZE64 #ifndef BLKGETSIZE64
# define BLKGETSIZE64 0x80041272 # define BLKGETSIZE64 0x80041272
#endif #endif
#ifndef BLKBSZSET #ifndef BLKBSZSET
# define BLKBSZSET 0x40041271 # define BLKBSZSET 0x40041271
#endif #endif
/* On Cygwin; use Win32 low level device operations. */ /* On Cygwin; use Win32 low level device operations. */

File diff suppressed because it is too large Load Diff

View File

@ -59,40 +59,40 @@ extern ntfschar NTFS_INDEX_O[3];
extern ntfschar NTFS_INDEX_Q[3]; extern ntfschar NTFS_INDEX_Q[3];
extern ntfschar NTFS_INDEX_R[3]; extern ntfschar NTFS_INDEX_R[3];
extern u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, extern u64 ntfs_inode_lookup_by_name( ntfs_inode *dir_ni,
const ntfschar *uname, const int uname_len); const ntfschar *uname, const int uname_len );
extern u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name); extern u64 ntfs_inode_lookup_by_mbsname( ntfs_inode *dir_ni, const char *name );
extern void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, extern void ntfs_inode_update_mbsname( ntfs_inode *dir_ni, const char *name,
u64 inum); u64 inum );
extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, extern ntfs_inode *ntfs_pathname_to_inode( ntfs_volume *vol, ntfs_inode *parent,
const char *pathname); const char *pathname );
extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, extern ntfs_inode *ntfs_create( ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, mode_t type); ntfschar *name, u8 name_len, mode_t type );
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, extern ntfs_inode *ntfs_create_device( ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, mode_t type, dev_t dev); ntfschar *name, u8 name_len, mode_t type, dev_t dev );
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid, extern ntfs_inode *ntfs_create_symlink( ntfs_inode *dir_ni, le32 securid,
ntfschar *name, u8 name_len, ntfschar *target, int target_len); ntfschar *name, u8 name_len, ntfschar *target, int target_len );
extern int ntfs_check_empty_dir(ntfs_inode *ni); extern int ntfs_check_empty_dir( ntfs_inode *ni );
extern int ntfs_delete(ntfs_volume *vol, const char *path, extern int ntfs_delete( ntfs_volume *vol, const char *path,
ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len); u8 name_len );
extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, extern int ntfs_link( ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
u8 name_len); u8 name_len );
/* /*
* File types (adapted from include <linux/fs.h>) * File types (adapted from include <linux/fs.h>)
*/ */
#define NTFS_DT_UNKNOWN 0 #define NTFS_DT_UNKNOWN 0
#define NTFS_DT_FIFO 1 #define NTFS_DT_FIFO 1
#define NTFS_DT_CHR 2 #define NTFS_DT_CHR 2
#define NTFS_DT_DIR 4 #define NTFS_DT_DIR 4
#define NTFS_DT_BLK 6 #define NTFS_DT_BLK 6
#define NTFS_DT_REG 8 #define NTFS_DT_REG 8
#define NTFS_DT_LNK 10 #define NTFS_DT_LNK 10
#define NTFS_DT_SOCK 12 #define NTFS_DT_SOCK 12
#define NTFS_DT_WHT 14 #define NTFS_DT_WHT 14
/* /*
* This is the "ntfs_filldir" function type, used by ntfs_readdir() to let * This is the "ntfs_filldir" function type, used by ntfs_readdir() to let
@ -100,27 +100,27 @@ extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
* This allows the caller to read directories into their application or * This allows the caller to read directories into their application or
* to have different dirent layouts depending on the binary type. * to have different dirent layouts depending on the binary type.
*/ */
typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name, typedef int ( *ntfs_filldir_t )( void *dirent, const ntfschar *name,
const int name_len, const int name_type, const s64 pos, const int name_len, const int name_type, const s64 pos,
const MFT_REF mref, const unsigned dt_type); const MFT_REF mref, const unsigned dt_type );
extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos, extern int ntfs_readdir( ntfs_inode *dir_ni, s64 *pos,
void *dirent, ntfs_filldir_t filldir); void *dirent, ntfs_filldir_t filldir );
ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni); ntfs_inode *ntfs_dir_parent_inode( ntfs_inode *ni );
int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, int ntfs_get_ntfs_dos_name( ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size); char *value, size_t size );
int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, int ntfs_set_ntfs_dos_name( ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags); const char *value, size_t size, int flags );
int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni); int ntfs_remove_ntfs_dos_name( ntfs_inode *ni, ntfs_inode *dir_ni );
#if CACHE_INODE_SIZE #if CACHE_INODE_SIZE
struct CACHED_GENERIC; struct CACHED_GENERIC;
extern int ntfs_dir_inode_hash(const struct CACHED_GENERIC *cached); extern int ntfs_dir_inode_hash( const struct CACHED_GENERIC *cached );
extern int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached); extern int ntfs_dir_lookup_hash( const struct CACHED_GENERIC *cached );
#endif #endif

View File

@ -1,7 +1,7 @@
/** /**
* efs.c - Limited processing of encrypted files * efs.c - Limited processing of encrypted files
* *
* This module is part of ntfs-3g library * This module is part of ntfs-3g library
* *
* Copyright (c) 2009 Martin Bene * Copyright (c) 2009 Martin Bene
* Copyright (c) 2009-2010 Jean-Pierre Andre * Copyright (c) 2009-2010 Jean-Pierre Andre
@ -58,256 +58,305 @@
#include "misc.h" #include "misc.h"
#include "efs.h" #include "efs.h"
#ifdef HAVE_SETXATTR /* extended attributes interface required */ #ifdef HAVE_SETXATTR /* extended attributes interface required */
static ntfschar logged_utility_stream_name[] = { static ntfschar logged_utility_stream_name[] =
const_cpu_to_le16('$'), {
const_cpu_to_le16('E'), const_cpu_to_le16( '$' ),
const_cpu_to_le16('F'), const_cpu_to_le16( 'E' ),
const_cpu_to_le16('S'), const_cpu_to_le16( 'F' ),
const_cpu_to_le16(0) const_cpu_to_le16( 'S' ),
const_cpu_to_le16( 0 )
} ; } ;
/* /*
* Get the ntfs EFS info into an extended attribute * Get the ntfs EFS info into an extended attribute
*/ */
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size) int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size )
{ {
EFS_ATTR_HEADER *efs_info; EFS_ATTR_HEADER *efs_info;
s64 attr_size = 0; s64 attr_size = 0;
if (ni) { if ( ni )
if (ni->flags & FILE_ATTR_ENCRYPTED) { {
efs_info = (EFS_ATTR_HEADER*)ntfs_attr_readall(ni, if ( ni->flags & FILE_ATTR_ENCRYPTED )
AT_LOGGED_UTILITY_STREAM,(ntfschar*)NULL, 0, {
&attr_size); efs_info = ( EFS_ATTR_HEADER* )ntfs_attr_readall( ni,
if (efs_info AT_LOGGED_UTILITY_STREAM, ( ntfschar* )NULL, 0,
&& (le32_to_cpu(efs_info->length) == attr_size)) { &attr_size );
if (attr_size <= (s64)size) { if ( efs_info
if (value) && ( le32_to_cpu( efs_info->length ) == attr_size ) )
memcpy(value,efs_info,attr_size); {
else { if ( attr_size <= ( s64 )size )
errno = EFAULT; {
attr_size = 0; if ( value )
} memcpy( value, efs_info, attr_size );
} else else
if (size) { {
errno = ERANGE; errno = EFAULT;
attr_size = 0; attr_size = 0;
} }
free (efs_info); }
} else { else if ( size )
if (efs_info) { {
free(efs_info); errno = ERANGE;
ntfs_log_error("Bad efs_info for inode %lld\n", attr_size = 0;
(long long)ni->mft_no); }
} else { free ( efs_info );
ntfs_log_error("Could not get efsinfo" }
" for inode %lld\n", else
(long long)ni->mft_no); {
} if ( efs_info )
errno = EIO; {
attr_size = 0; free( efs_info );
} ntfs_log_error( "Bad efs_info for inode %lld\n",
} else { ( long long )ni->mft_no );
errno = ENODATA; }
ntfs_log_trace("Inode %lld is not encrypted\n", else
(long long)ni->mft_no); {
} ntfs_log_error( "Could not get efsinfo"
} " for inode %lld\n",
return (attr_size ? (int)attr_size : -errno); ( long long )ni->mft_no );
}
errno = EIO;
attr_size = 0;
}
}
else
{
errno = ENODATA;
ntfs_log_trace( "Inode %lld is not encrypted\n",
( long long )ni->mft_no );
}
}
return ( attr_size ? ( int )attr_size : -errno );
} }
/* /*
* Fix all encrypted AT_DATA attributes of an inode * Fix all encrypted AT_DATA attributes of an inode
* *
* The fix may require making an attribute non resident, which * The fix may require making an attribute non resident, which
* requires more space in the MFT record, and may cause some * requires more space in the MFT record, and may cause some
* attribute to be expelled and the full record to be reorganized. * attribute to be expelled and the full record to be reorganized.
* When this happens, the search for data attributes has to be * When this happens, the search for data attributes has to be
* reinitialized. * reinitialized.
* *
* Returns zero if successful. * Returns zero if successful.
* -1 if there is a problem. * -1 if there is a problem.
*/ */
static int fixup_loop(ntfs_inode *ni) static int fixup_loop( ntfs_inode *ni )
{ {
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
ntfs_attr *na; ntfs_attr *na;
ATTR_RECORD *a; ATTR_RECORD *a;
BOOL restart; BOOL restart;
BOOL first; BOOL first;
int cnt; int cnt;
int maxcnt; int maxcnt;
int res = 0; int res = 0;
maxcnt = 0; maxcnt = 0;
do { do
restart = FALSE; {
ctx = ntfs_attr_get_search_ctx(ni, NULL); restart = FALSE;
if (!ctx) { ctx = ntfs_attr_get_search_ctx( ni, NULL );
ntfs_log_error("Failed to get ctx for efs\n"); if ( !ctx )
res = -1; {
} ntfs_log_error( "Failed to get ctx for efs\n" );
cnt = 0; res = -1;
while (!restart && !res }
&& !ntfs_attr_lookup(AT_DATA, NULL, 0, cnt = 0;
CASE_SENSITIVE, 0, NULL, 0, ctx)) { while ( !restart && !res
cnt++; && !ntfs_attr_lookup( AT_DATA, NULL, 0,
a = ctx->attr; CASE_SENSITIVE, 0, NULL, 0, ctx ) )
na = ntfs_attr_open(ctx->ntfs_ino, AT_DATA, {
(ntfschar*)((u8*)a + le16_to_cpu(a->name_offset)), cnt++;
a->name_length); a = ctx->attr;
if (!na) { na = ntfs_attr_open( ctx->ntfs_ino, AT_DATA,
ntfs_log_error("can't open DATA Attribute\n"); ( ntfschar* )( ( u8* )a + le16_to_cpu( a->name_offset ) ),
res = -1; a->name_length );
} if ( !na )
if (na && !(ctx->attr->flags & ATTR_IS_ENCRYPTED)) { {
if (!NAttrNonResident(na) ntfs_log_error( "can't open DATA Attribute\n" );
&& ntfs_attr_make_non_resident(na, ctx)) { res = -1;
/* }
* ntfs_attr_make_non_resident fails if there if ( na && !( ctx->attr->flags & ATTR_IS_ENCRYPTED ) )
* is not enough space in the MFT record. {
* When this happens, force making non-resident if ( !NAttrNonResident( na )
* so that some other attribute is expelled. && ntfs_attr_make_non_resident( na, ctx ) )
*/ {
if (ntfs_attr_force_non_resident(na)) { /*
res = -1; * ntfs_attr_make_non_resident fails if there
} else { * is not enough space in the MFT record.
/* make sure there is some progress */ * When this happens, force making non-resident
if (cnt <= maxcnt) { * so that some other attribute is expelled.
errno = EIO; */
ntfs_log_error("Multiple failure" if ( ntfs_attr_force_non_resident( na ) )
" making non resident\n"); {
res = -1; res = -1;
} else { }
ntfs_attr_put_search_ctx(ctx); else
ctx = (ntfs_attr_search_ctx*)NULL; {
restart = TRUE; /* make sure there is some progress */
maxcnt = cnt; if ( cnt <= maxcnt )
} {
} errno = EIO;
} ntfs_log_error( "Multiple failure"
if (!restart && !res " making non resident\n" );
&& ntfs_efs_fixup_attribute(ctx, na)) { res = -1;
ntfs_log_error("Error in efs fixup of AT_DATA Attribute\n"); }
res = -1; else
} {
} ntfs_attr_put_search_ctx( ctx );
if (na) ctx = ( ntfs_attr_search_ctx* )NULL;
ntfs_attr_close(na); restart = TRUE;
} maxcnt = cnt;
first = FALSE; }
} while (restart && !res); }
if (ctx) }
ntfs_attr_put_search_ctx(ctx); if ( !restart && !res
return (res); && ntfs_efs_fixup_attribute( ctx, na ) )
{
ntfs_log_error( "Error in efs fixup of AT_DATA Attribute\n" );
res = -1;
}
}
if ( na )
ntfs_attr_close( na );
}
first = FALSE;
}
while ( restart && !res );
if ( ctx )
ntfs_attr_put_search_ctx( ctx );
return ( res );
} }
/* /*
* Set the efs data from an extended attribute * Set the efs data from an extended attribute
* Warning : the new data is not checked * Warning : the new data is not checked
* Returns 0, or -1 if there is a problem * Returns 0, or -1 if there is a problem
*/ */
int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size, int ntfs_set_efs_info( ntfs_inode *ni, const char *value, size_t size,
int flags) int flags )
{
int res;
int written;
ntfs_attr *na;
const EFS_ATTR_HEADER *info_header;
res = 0; {
if (ni && value && size) { int res;
if (ni->flags & (FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED)) { int written;
if (ni->flags & FILE_ATTR_ENCRYPTED) { ntfs_attr *na;
ntfs_log_trace("Inode %lld already encrypted\n", const EFS_ATTR_HEADER *info_header;
(long long)ni->mft_no);
errno = EEXIST; res = 0;
} else { if ( ni && value && size )
/* {
* Possible problem : if encrypted file was if ( ni->flags & ( FILE_ATTR_ENCRYPTED | FILE_ATTR_COMPRESSED ) )
* restored in a compressed directory, it was {
* restored as compressed. if ( ni->flags & FILE_ATTR_ENCRYPTED )
* TODO : decompress first. {
*/ ntfs_log_trace( "Inode %lld already encrypted\n",
ntfs_log_error("Inode %lld cannot be encrypted and compressed\n", ( long long )ni->mft_no );
(long long)ni->mft_no); errno = EEXIST;
errno = EIO; }
} else
return -1; {
} /*
info_header = (const EFS_ATTR_HEADER*)value; * Possible problem : if encrypted file was
/* make sure we get a likely efsinfo */ * restored in a compressed directory, it was
if (le32_to_cpu(info_header->length) != size) { * restored as compressed.
errno = EINVAL; * TODO : decompress first.
return (-1); */
} ntfs_log_error( "Inode %lld cannot be encrypted and compressed\n",
if (!ntfs_attr_exist(ni,AT_LOGGED_UTILITY_STREAM, ( long long )ni->mft_no );
(ntfschar*)NULL,0)) { errno = EIO;
if (!(flags & XATTR_REPLACE)) { }
/* return -1;
* no logged_utility_stream attribute : add one, }
* apparently, this does not feed the new value in info_header = ( const EFS_ATTR_HEADER* )value;
*/ /* make sure we get a likely efsinfo */
res = ntfs_attr_add(ni,AT_LOGGED_UTILITY_STREAM, if ( le32_to_cpu( info_header->length ) != size )
logged_utility_stream_name,4, {
(u8*)NULL,(s64)size); errno = EINVAL;
} else { return ( -1 );
errno = ENODATA; }
res = -1; if ( !ntfs_attr_exist( ni, AT_LOGGED_UTILITY_STREAM,
} ( ntfschar* )NULL, 0 ) )
} else { {
errno = EEXIST; if ( !( flags & XATTR_REPLACE ) )
res = -1; {
} /*
if (!res) { * no logged_utility_stream attribute : add one,
/* * apparently, this does not feed the new value in
* open and update the existing efs data */
*/ res = ntfs_attr_add( ni, AT_LOGGED_UTILITY_STREAM,
na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, logged_utility_stream_name, 4,
logged_utility_stream_name, 4); ( u8* )NULL, ( s64 )size );
if (na) { }
/* resize attribute */ else
res = ntfs_attr_truncate(na, (s64)size); {
/* overwrite value if any */ errno = ENODATA;
if (!res && value) { res = -1;
written = (int)ntfs_attr_pwrite(na, }
(s64)0, (s64)size, value); }
if (written != (s64)size) { else
ntfs_log_error("Failed to " {
"update efs data\n"); errno = EEXIST;
errno = EIO; res = -1;
res = -1; }
} if ( !res )
} {
ntfs_attr_close(na); /*
} else * open and update the existing efs data
res = -1; */
} na = ntfs_attr_open( ni, AT_LOGGED_UTILITY_STREAM,
if (!res) { logged_utility_stream_name, 4 );
/* Don't handle AT_DATA Attribute(s) if inode is a directory */ if ( na )
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { {
/* iterate over AT_DATA attributes */ /* resize attribute */
/* set encrypted flag, truncate attribute to match padding bytes */ res = ntfs_attr_truncate( na, ( s64 )size );
/* overwrite value if any */
if (fixup_loop(ni)) if ( !res && value )
return -1; {
} written = ( int )ntfs_attr_pwrite( na,
ni->flags |= FILE_ATTR_ENCRYPTED; ( s64 )0, ( s64 )size, value );
NInoSetDirty(ni); if ( written != ( s64 )size )
NInoFileNameSetDirty(ni); {
} ntfs_log_error( "Failed to "
} else { "update efs data\n" );
errno = EINVAL; errno = EIO;
res = -1; res = -1;
} }
return (res ? -1 : 0); }
ntfs_attr_close( na );
}
else
res = -1;
}
if ( !res )
{
/* Don't handle AT_DATA Attribute(s) if inode is a directory */
if ( !( ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ) )
{
/* iterate over AT_DATA attributes */
/* set encrypted flag, truncate attribute to match padding bytes */
if ( fixup_loop( ni ) )
return -1;
}
ni->flags |= FILE_ATTR_ENCRYPTED;
NInoSetDirty( ni );
NInoFileNameSetDirty( ni );
}
}
else
{
errno = EINVAL;
res = -1;
}
return ( res ? -1 : 0 );
} }
/* /*
@ -315,125 +364,144 @@ int ntfs_set_efs_info(ntfs_inode *ni, const char *value, size_t size,
* read padding length from last two bytes * read padding length from last two bytes
* truncate attribute, make non-resident, * truncate attribute, make non-resident,
* set data size to match padding length * set data size to match padding length
* set ATTR_IS_ENCRYPTED flag on attribute * set ATTR_IS_ENCRYPTED flag on attribute
* *
* Return 0 if successful * Return 0 if successful
* -1 if failed (errno tells why) * -1 if failed (errno tells why)
*/ */
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na) int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na )
{ {
u64 newsize; u64 newsize;
u64 oldsize; u64 oldsize;
le16 appended_bytes; le16 appended_bytes;
u16 padding_length; u16 padding_length;
ntfs_inode *ni; ntfs_inode *ni;
BOOL close_ctx = FALSE; BOOL close_ctx = FALSE;
if (!na) { if ( !na )
ntfs_log_error("no na specified for efs_fixup_attribute\n"); {
goto err_out; ntfs_log_error( "no na specified for efs_fixup_attribute\n" );
} goto err_out;
if (!ctx) { }
ctx = ntfs_attr_get_search_ctx(na->ni, NULL); if ( !ctx )
if (!ctx) { {
ntfs_log_error("Failed to get ctx for efs\n"); ctx = ntfs_attr_get_search_ctx( na->ni, NULL );
goto err_out; if ( !ctx )
} {
close_ctx = TRUE; ntfs_log_error( "Failed to get ctx for efs\n" );
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, goto err_out;
CASE_SENSITIVE, 0, NULL, 0, ctx)) { }
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); close_ctx = TRUE;
goto err_out; if ( ntfs_attr_lookup( AT_DATA, na->name, na->name_len,
} CASE_SENSITIVE, 0, NULL, 0, ctx ) )
} else { {
if (!NAttrNonResident(na)) { ntfs_log_error( "attr lookup for AT_DATA attribute failed in efs fixup\n" );
ntfs_log_error("Cannot make non resident" goto err_out;
" when a context has been allocated\n"); }
goto err_out; }
} else
} {
if ( !NAttrNonResident( na ) )
{
ntfs_log_error( "Cannot make non resident"
" when a context has been allocated\n" );
goto err_out;
}
}
/* no extra bytes are added to void attributes */ /* no extra bytes are added to void attributes */
oldsize = na->data_size; oldsize = na->data_size;
if (oldsize) { if ( oldsize )
/* make sure size is valid for a raw encrypted stream */ {
if ((oldsize & 511) != 2) { /* make sure size is valid for a raw encrypted stream */
ntfs_log_error("Bad raw encrypted stream\n"); if ( ( oldsize & 511 ) != 2 )
goto err_out; {
} ntfs_log_error( "Bad raw encrypted stream\n" );
/* read padding length from last two bytes of attribute */ goto err_out;
if (ntfs_attr_pread(na, oldsize - 2, 2, &appended_bytes) != 2) { }
ntfs_log_error("Error reading padding length\n"); /* read padding length from last two bytes of attribute */
goto err_out; if ( ntfs_attr_pread( na, oldsize - 2, 2, &appended_bytes ) != 2 )
} {
padding_length = le16_to_cpu(appended_bytes); ntfs_log_error( "Error reading padding length\n" );
if (padding_length > 511 || padding_length > na->data_size-2) { goto err_out;
errno = EINVAL; }
ntfs_log_error("invalid padding length %d for data_size %lld\n", padding_length = le16_to_cpu( appended_bytes );
padding_length, (long long)oldsize); if ( padding_length > 511 || padding_length > na->data_size - 2 )
goto err_out; {
} errno = EINVAL;
newsize = oldsize - padding_length - 2; ntfs_log_error( "invalid padding length %d for data_size %lld\n",
/* padding_length, ( long long )oldsize );
* truncate attribute to possibly free clusters allocated goto err_out;
* for the last two bytes, but do not truncate to new size }
* to avoid losing useful data newsize = oldsize - padding_length - 2;
*/ /*
if (ntfs_attr_truncate(na, oldsize - 2)) { * truncate attribute to possibly free clusters allocated
ntfs_log_error("Error truncating attribute\n"); * for the last two bytes, but do not truncate to new size
goto err_out; * to avoid losing useful data
} */
} else if ( ntfs_attr_truncate( na, oldsize - 2 ) )
newsize = 0; {
ntfs_log_error( "Error truncating attribute\n" );
goto err_out;
}
}
else
newsize = 0;
/* /*
* Encrypted AT_DATA Attributes MUST be non-resident * Encrypted AT_DATA Attributes MUST be non-resident
* This has to be done after the attribute is resized, as * This has to be done after the attribute is resized, as
* resizing down to zero may cause the attribute to be made * resizing down to zero may cause the attribute to be made
* resident. * resident.
*/ */
if (!NAttrNonResident(na) if ( !NAttrNonResident( na )
&& ntfs_attr_make_non_resident(na, ctx)) { && ntfs_attr_make_non_resident( na, ctx ) )
if (!close_ctx {
|| ntfs_attr_force_non_resident(na)) { if ( !close_ctx
ntfs_log_error("Error making DATA attribute non-resident\n"); || ntfs_attr_force_non_resident( na ) )
goto err_out; {
} else { ntfs_log_error( "Error making DATA attribute non-resident\n" );
/* goto err_out;
* must reinitialize context after forcing }
* non-resident. We need a context for updating else
* the state, and at this point, we are sure {
* the context is not used elsewhere. /*
*/ * must reinitialize context after forcing
ntfs_attr_reinit_search_ctx(ctx); * non-resident. We need a context for updating
if (ntfs_attr_lookup(AT_DATA, na->name, na->name_len, * the state, and at this point, we are sure
CASE_SENSITIVE, 0, NULL, 0, ctx)) { * the context is not used elsewhere.
ntfs_log_error("attr lookup for AT_DATA attribute failed in efs fixup\n"); */
goto err_out; ntfs_attr_reinit_search_ctx( ctx );
} if ( ntfs_attr_lookup( AT_DATA, na->name, na->name_len,
} CASE_SENSITIVE, 0, NULL, 0, ctx ) )
} {
ni = na->ni; ntfs_log_error( "attr lookup for AT_DATA attribute failed in efs fixup\n" );
if (!na->name_len) { goto err_out;
ni->data_size = newsize; }
ni->allocated_size = na->allocated_size; }
} }
NInoSetDirty(ni); ni = na->ni;
NInoFileNameSetDirty(ni); if ( !na->name_len )
{
ni->data_size = newsize;
ni->allocated_size = na->allocated_size;
}
NInoSetDirty( ni );
NInoFileNameSetDirty( ni );
ctx->attr->data_size = cpu_to_le64(newsize); ctx->attr->data_size = cpu_to_le64( newsize );
if (le64_to_cpu(ctx->attr->initialized_size) > newsize) if ( le64_to_cpu( ctx->attr->initialized_size ) > newsize )
ctx->attr->initialized_size = ctx->attr->data_size; ctx->attr->initialized_size = ctx->attr->data_size;
ctx->attr->flags |= ATTR_IS_ENCRYPTED; ctx->attr->flags |= ATTR_IS_ENCRYPTED;
if (close_ctx) if ( close_ctx )
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx( ctx );
return (0); return ( 0 );
err_out: err_out:
if (close_ctx && ctx) if ( close_ctx && ctx )
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx( ctx );
return (-1); return ( -1 );
} }
#endif /* HAVE_SETXATTR */ #endif /* HAVE_SETXATTR */

View File

@ -21,10 +21,10 @@
#ifndef EFS_H #ifndef EFS_H
#define EFS_H #define EFS_H
int ntfs_get_efs_info(ntfs_inode *ni, char *value, size_t size); int ntfs_get_efs_info( ntfs_inode *ni, char *value, size_t size );
int ntfs_set_efs_info(ntfs_inode *ni, int ntfs_set_efs_info( ntfs_inode *ni,
const char *value, size_t size, int flags); const char *value, size_t size, int flags );
int ntfs_efs_fixup_attribute(ntfs_attr_search_ctx *ctx, ntfs_attr *na); int ntfs_efs_fixup_attribute( ntfs_attr_search_ctx *ctx, ntfs_attr *na );
#endif /* EFS_H */ #endif /* EFS_H */

View File

@ -1,5 +1,5 @@
/* /*
* endians.h - Definitions related to handling of byte ordering. * endians.h - Definitions related to handling of byte ordering.
* Originated from the Linux-NTFS project. * Originated from the Linux-NTFS project.
* *
* Copyright (c) 2000-2005 Anton Altaparmakov * Copyright (c) 2000-2005 Anton Altaparmakov
@ -29,9 +29,9 @@
/* /*
* Notes: * Notes:
* We define the conversion functions including typecasts since the * We define the conversion functions including typecasts since the
* defaults don't necessarily perform appropriate typecasts. * defaults don't necessarily perform appropriate typecasts.
* Also, using our own functions means that we can change them if it * Also, using our own functions means that we can change them if it
* turns out that we do need to use the unaligned access macros on * turns out that we do need to use the unaligned access macros on
* architectures requiring aligned memory accesses... * architectures requiring aligned memory accesses...
*/ */
@ -53,59 +53,59 @@
#endif #endif
#ifndef __BYTE_ORDER #ifndef __BYTE_ORDER
# if defined(_BYTE_ORDER) # if defined(_BYTE_ORDER)
# define __BYTE_ORDER _BYTE_ORDER # define __BYTE_ORDER _BYTE_ORDER
# define __LITTLE_ENDIAN _LITTLE_ENDIAN # define __LITTLE_ENDIAN _LITTLE_ENDIAN
# define __BIG_ENDIAN _BIG_ENDIAN # define __BIG_ENDIAN _BIG_ENDIAN
# elif defined(BYTE_ORDER) # elif defined(BYTE_ORDER)
# define __BYTE_ORDER BYTE_ORDER # define __BYTE_ORDER BYTE_ORDER
# define __LITTLE_ENDIAN LITTLE_ENDIAN # define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __BIG_ENDIAN BIG_ENDIAN # define __BIG_ENDIAN BIG_ENDIAN
# elif defined(__BYTE_ORDER__) # elif defined(__BYTE_ORDER__)
# define __BYTE_ORDER __BYTE_ORDER__ # define __BYTE_ORDER __BYTE_ORDER__
# define __LITTLE_ENDIAN __LITTLE_ENDIAN__ # define __LITTLE_ENDIAN __LITTLE_ENDIAN__
# define __BIG_ENDIAN __BIG_ENDIAN__ # define __BIG_ENDIAN __BIG_ENDIAN__
# elif (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \ # elif (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
defined(WORDS_LITTLEENDIAN) defined(WORDS_LITTLEENDIAN)
# define __BYTE_ORDER 1 # define __BYTE_ORDER 1
# define __LITTLE_ENDIAN 1 # define __LITTLE_ENDIAN 1
# define __BIG_ENDIAN 0 # define __BIG_ENDIAN 0
# elif (!defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) || \ # elif (!defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) || \
defined(WORDS_BIGENDIAN) defined(WORDS_BIGENDIAN)
# define __BYTE_ORDER 0 # define __BYTE_ORDER 0
# define __LITTLE_ENDIAN 1 # define __LITTLE_ENDIAN 1
# define __BIG_ENDIAN 0 # define __BIG_ENDIAN 0
# else # else
# error "__BYTE_ORDER is not defined." # error "__BYTE_ORDER is not defined."
# endif # endif
#endif #endif
#define __ntfs_bswap_constant_16(x) \ #define __ntfs_bswap_constant_16(x) \
(u16)((((u16)(x) & 0xff00) >> 8) | \ (u16)((((u16)(x) & 0xff00) >> 8) | \
(((u16)(x) & 0x00ff) << 8)) (((u16)(x) & 0x00ff) << 8))
#define __ntfs_bswap_constant_32(x) \ #define __ntfs_bswap_constant_32(x) \
(u32)((((u32)(x) & 0xff000000u) >> 24) | \ (u32)((((u32)(x) & 0xff000000u) >> 24) | \
(((u32)(x) & 0x00ff0000u) >> 8) | \ (((u32)(x) & 0x00ff0000u) >> 8) | \
(((u32)(x) & 0x0000ff00u) << 8) | \ (((u32)(x) & 0x0000ff00u) << 8) | \
(((u32)(x) & 0x000000ffu) << 24)) (((u32)(x) & 0x000000ffu) << 24))
#define __ntfs_bswap_constant_64(x) \ #define __ntfs_bswap_constant_64(x) \
(u64)((((u64)(x) & 0xff00000000000000ull) >> 56) | \ (u64)((((u64)(x) & 0xff00000000000000ull) >> 56) | \
(((u64)(x) & 0x00ff000000000000ull) >> 40) | \ (((u64)(x) & 0x00ff000000000000ull) >> 40) | \
(((u64)(x) & 0x0000ff0000000000ull) >> 24) | \ (((u64)(x) & 0x0000ff0000000000ull) >> 24) | \
(((u64)(x) & 0x000000ff00000000ull) >> 8) | \ (((u64)(x) & 0x000000ff00000000ull) >> 8) | \
(((u64)(x) & 0x00000000ff000000ull) << 8) | \ (((u64)(x) & 0x00000000ff000000ull) << 8) | \
(((u64)(x) & 0x0000000000ff0000ull) << 24) | \ (((u64)(x) & 0x0000000000ff0000ull) << 24) | \
(((u64)(x) & 0x000000000000ff00ull) << 40) | \ (((u64)(x) & 0x000000000000ff00ull) << 40) | \
(((u64)(x) & 0x00000000000000ffull) << 56)) (((u64)(x) & 0x00000000000000ffull) << 56))
#ifdef HAVE_BYTESWAP_H #ifdef HAVE_BYTESWAP_H
# include <byteswap.h> # include <byteswap.h>
#else #else
# define bswap_16(x) __ntfs_bswap_constant_16(x) # define bswap_16(x) __ntfs_bswap_constant_16(x)
# define bswap_32(x) __ntfs_bswap_constant_32(x) # define bswap_32(x) __ntfs_bswap_constant_32(x)
# define bswap_64(x) __ntfs_bswap_constant_64(x) # define bswap_64(x) __ntfs_bswap_constant_64(x)
#endif #endif
#if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) #if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN)
@ -152,52 +152,52 @@
/* Unsigned from LE to CPU conversion. */ /* Unsigned from LE to CPU conversion. */
#define le16_to_cpu(x) (u16)__le16_to_cpu((u16)(x)) #define le16_to_cpu(x) (u16)__le16_to_cpu((u16)(x))
#define le32_to_cpu(x) (u32)__le32_to_cpu((u32)(x)) #define le32_to_cpu(x) (u32)__le32_to_cpu((u32)(x))
#define le64_to_cpu(x) (u64)__le64_to_cpu((u64)(x)) #define le64_to_cpu(x) (u64)__le64_to_cpu((u64)(x))
#define le16_to_cpup(x) (u16)__le16_to_cpu(*(const u16*)(x)) #define le16_to_cpup(x) (u16)__le16_to_cpu(*(const u16*)(x))
#define le32_to_cpup(x) (u32)__le32_to_cpu(*(const u32*)(x)) #define le32_to_cpup(x) (u32)__le32_to_cpu(*(const u32*)(x))
#define le64_to_cpup(x) (u64)__le64_to_cpu(*(const u64*)(x)) #define le64_to_cpup(x) (u64)__le64_to_cpu(*(const u64*)(x))
/* Signed from LE to CPU conversion. */ /* Signed from LE to CPU conversion. */
#define sle16_to_cpu(x) (s16)__le16_to_cpu((s16)(x)) #define sle16_to_cpu(x) (s16)__le16_to_cpu((s16)(x))
#define sle32_to_cpu(x) (s32)__le32_to_cpu((s32)(x)) #define sle32_to_cpu(x) (s32)__le32_to_cpu((s32)(x))
#define sle64_to_cpu(x) (s64)__le64_to_cpu((s64)(x)) #define sle64_to_cpu(x) (s64)__le64_to_cpu((s64)(x))
#define sle16_to_cpup(x) (s16)__le16_to_cpu(*(s16*)(x)) #define sle16_to_cpup(x) (s16)__le16_to_cpu(*(s16*)(x))
#define sle32_to_cpup(x) (s32)__le32_to_cpu(*(s32*)(x)) #define sle32_to_cpup(x) (s32)__le32_to_cpu(*(s32*)(x))
#define sle64_to_cpup(x) (s64)__le64_to_cpu(*(s64*)(x)) #define sle64_to_cpup(x) (s64)__le64_to_cpu(*(s64*)(x))
/* Unsigned from CPU to LE conversion. */ /* Unsigned from CPU to LE conversion. */
#define cpu_to_le16(x) (u16)__cpu_to_le16((u16)(x)) #define cpu_to_le16(x) (u16)__cpu_to_le16((u16)(x))
#define cpu_to_le32(x) (u32)__cpu_to_le32((u32)(x)) #define cpu_to_le32(x) (u32)__cpu_to_le32((u32)(x))
#define cpu_to_le64(x) (u64)__cpu_to_le64((u64)(x)) #define cpu_to_le64(x) (u64)__cpu_to_le64((u64)(x))
#define cpu_to_le16p(x) (u16)__cpu_to_le16(*(u16*)(x)) #define cpu_to_le16p(x) (u16)__cpu_to_le16(*(u16*)(x))
#define cpu_to_le32p(x) (u32)__cpu_to_le32(*(u32*)(x)) #define cpu_to_le32p(x) (u32)__cpu_to_le32(*(u32*)(x))
#define cpu_to_le64p(x) (u64)__cpu_to_le64(*(u64*)(x)) #define cpu_to_le64p(x) (u64)__cpu_to_le64(*(u64*)(x))
/* Signed from CPU to LE conversion. */ /* Signed from CPU to LE conversion. */
#define cpu_to_sle16(x) (s16)__cpu_to_le16((s16)(x)) #define cpu_to_sle16(x) (s16)__cpu_to_le16((s16)(x))
#define cpu_to_sle32(x) (s32)__cpu_to_le32((s32)(x)) #define cpu_to_sle32(x) (s32)__cpu_to_le32((s32)(x))
#define cpu_to_sle64(x) (s64)__cpu_to_le64((s64)(x)) #define cpu_to_sle64(x) (s64)__cpu_to_le64((s64)(x))
#define cpu_to_sle16p(x) (s16)__cpu_to_le16(*(s16*)(x)) #define cpu_to_sle16p(x) (s16)__cpu_to_le16(*(s16*)(x))
#define cpu_to_sle32p(x) (s32)__cpu_to_le32(*(s32*)(x)) #define cpu_to_sle32p(x) (s32)__cpu_to_le32(*(s32*)(x))
#define cpu_to_sle64p(x) (s64)__cpu_to_le64(*(s64*)(x)) #define cpu_to_sle64p(x) (s64)__cpu_to_le64(*(s64*)(x))
/* Constant endianness conversion defines. */ /* Constant endianness conversion defines. */
#define const_le16_to_cpu(x) __constant_le16_to_cpu(x) #define const_le16_to_cpu(x) __constant_le16_to_cpu(x)
#define const_le32_to_cpu(x) __constant_le32_to_cpu(x) #define const_le32_to_cpu(x) __constant_le32_to_cpu(x)
#define const_le64_to_cpu(x) __constant_le64_to_cpu(x) #define const_le64_to_cpu(x) __constant_le64_to_cpu(x)
#define const_cpu_to_le16(x) __constant_cpu_to_le16(x) #define const_cpu_to_le16(x) __constant_cpu_to_le16(x)
#define const_cpu_to_le32(x) __constant_cpu_to_le32(x) #define const_cpu_to_le32(x) __constant_cpu_to_le32(x)
#define const_cpu_to_le64(x) __constant_cpu_to_le64(x) #define const_cpu_to_le64(x) __constant_cpu_to_le64(x)
#endif /* defined _NTFS_ENDIANS_H */ #endif /* defined _NTFS_ENDIANS_H */

View File

@ -66,83 +66,93 @@
#define DEV_FD(dev) ((gekko_fd *)dev->d_private) #define DEV_FD(dev) ((gekko_fd *)dev->d_private)
/* Prototypes */ /* Prototypes */
static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s64 count, void *buf); static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset, s64 count, void *buf );
static bool ntfs_device_gekko_io_readsectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer); static bool ntfs_device_gekko_io_readsectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer );
static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset, s64 count, const void *buf); static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset, s64 count, const void *buf );
static bool ntfs_device_gekko_io_writesectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer); static bool ntfs_device_gekko_io_writesectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer );
/** /**
* *
*/ */
static int ntfs_device_gekko_io_open(struct ntfs_device *dev, int flags) static int ntfs_device_gekko_io_open( struct ntfs_device *dev, int flags )
{ {
ntfs_log_trace("dev %p, flags %i\n", dev, flags); ntfs_log_trace( "dev %p, flags %i\n", dev, flags );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Get the device interface // Get the device interface
const DISC_INTERFACE* interface = fd->interface; const DISC_INTERFACE* interface = fd->interface;
if (!interface) { if ( !interface )
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Start the device interface and ensure that it is inserted // Start the device interface and ensure that it is inserted
if (!interface->startup()) { if ( !interface->startup() )
ntfs_log_perror("device failed to start\n"); {
ntfs_log_perror( "device failed to start\n" );
errno = EIO; errno = EIO;
return -1; return -1;
} }
if (!interface->isInserted()) { if ( !interface->isInserted() )
ntfs_log_perror("device media is not inserted\n"); {
ntfs_log_perror( "device media is not inserted\n" );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Check that the device isn't already open (used by another volume?) // Check that the device isn't already open (used by another volume?)
if (NDevOpen(dev)) { if ( NDevOpen( dev ) )
ntfs_log_perror("device is busy (already open)\n"); {
ntfs_log_perror( "device is busy (already open)\n" );
errno = EBUSY; errno = EBUSY;
return -1; return -1;
} }
// Check that there is a valid NTFS boot sector at the start of the device // Check that there is a valid NTFS boot sector at the start of the device
NTFS_BOOT_SECTOR boot; NTFS_BOOT_SECTOR boot;
if (interface->readSectors(fd->startSector, 1, &boot)) { if ( interface->readSectors( fd->startSector, 1, &boot ) )
if (!ntfs_boot_sector_is_ntfs(&boot)) { {
if ( !ntfs_boot_sector_is_ntfs( &boot ) )
{
errno = EINVALPART; errno = EINVALPART;
return -1; return -1;
} }
} else { }
ntfs_log_perror("read failure @ sector %d\n", fd->startSector); else
{
ntfs_log_perror( "read failure @ sector %d\n", fd->startSector );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Parse the boot sector // Parse the boot sector
fd->hiddenSectors = le32_to_cpu(boot.bpb.hidden_sectors); fd->hiddenSectors = le32_to_cpu( boot.bpb.hidden_sectors );
fd->sectorSize = le16_to_cpu(boot.bpb.bytes_per_sector); fd->sectorSize = le16_to_cpu( boot.bpb.bytes_per_sector );
fd->sectorCount = sle64_to_cpu(boot.number_of_sectors); fd->sectorCount = sle64_to_cpu( boot.number_of_sectors );
fd->pos = 0; fd->pos = 0;
fd->len = (fd->sectorCount * fd->sectorSize); fd->len = ( fd->sectorCount * fd->sectorSize );
fd->ino = le64_to_cpu(boot.volume_serial_number); fd->ino = le64_to_cpu( boot.volume_serial_number );
// Mark the device as read-only (if required) // Mark the device as read-only (if required)
if (flags & O_RDONLY) { if ( flags & O_RDONLY )
NDevSetReadOnly(dev); {
NDevSetReadOnly( dev );
} }
// Create the cache // Create the cache
fd->cache = _NTFS_cache_constructor(fd->cachePageCount, fd->cachePageSize, interface, fd->startSector + fd->sectorCount, fd->sectorSize); fd->cache = _NTFS_cache_constructor( fd->cachePageCount, fd->cachePageSize, interface, fd->startSector + fd->sectorCount, fd->sectorSize );
// Mark the device as open // Mark the device as open
NDevSetBlock(dev); NDevSetBlock( dev );
NDevSetOpen(dev); NDevSetOpen( dev );
return 0; return 0;
} }
@ -150,43 +160,47 @@ static int ntfs_device_gekko_io_open(struct ntfs_device *dev, int flags)
/** /**
* *
*/ */
static int ntfs_device_gekko_io_close(struct ntfs_device *dev) static int ntfs_device_gekko_io_close( struct ntfs_device *dev )
{ {
ntfs_log_trace("dev %p\n", dev); ntfs_log_trace( "dev %p\n", dev );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Check that the device is actually open // Check that the device is actually open
if (!NDevOpen(dev)) { if ( !NDevOpen( dev ) )
ntfs_log_perror("device is not open\n"); {
ntfs_log_perror( "device is not open\n" );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Mark the device as closed // Mark the device as closed
NDevClearOpen(dev); NDevClearOpen( dev );
NDevClearBlock(dev); NDevClearBlock( dev );
// Flush the device (if dirty and not read-only) // Flush the device (if dirty and not read-only)
if (NDevDirty(dev) && !NDevReadOnly(dev)) { if ( NDevDirty( dev ) && !NDevReadOnly( dev ) )
ntfs_log_debug("device is dirty, will now sync\n"); {
ntfs_log_debug( "device is dirty, will now sync\n" );
// ...? // ...?
// Mark the device as clean // Mark the device as clean
NDevClearDirty(dev); NDevClearDirty( dev );
} }
// Flush and destroy the cache (if required) // Flush and destroy the cache (if required)
if (fd->cache) { if ( fd->cache )
_NTFS_cache_flush(fd->cache); {
_NTFS_cache_destructor(fd->cache); _NTFS_cache_flush( fd->cache );
_NTFS_cache_destructor( fd->cache );
} }
// Shutdown the device interface // Shutdown the device interface
@ -196,7 +210,7 @@ static int ntfs_device_gekko_io_close(struct ntfs_device *dev)
}*/ }*/
// Free the device driver private data // Free the device driver private data
ntfs_free(dev->d_private); ntfs_free( dev->d_private );
dev->d_private = NULL; dev->d_private = NULL;
return 0; return 0;
@ -205,22 +219,24 @@ static int ntfs_device_gekko_io_close(struct ntfs_device *dev)
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_seek(struct ntfs_device *dev, s64 offset, int whence) static s64 ntfs_device_gekko_io_seek( struct ntfs_device *dev, s64 offset, int whence )
{ {
ntfs_log_trace("dev %p, offset %Li, whence %i\n", dev, offset, whence); ntfs_log_trace( "dev %p, offset %Li, whence %i\n", dev, offset, whence );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Set the current position on the device (in bytes) // Set the current position on the device (in bytes)
switch(whence) { switch ( whence )
case SEEK_SET: fd->pos = MIN(MAX(offset, 0), fd->len); break; {
case SEEK_CUR: fd->pos = MIN(MAX(fd->pos + offset, 0), fd->len); break; case SEEK_SET: fd->pos = MIN( MAX( offset, 0 ), fd->len ); break;
case SEEK_END: fd->pos = MIN(MAX(fd->len + offset, 0), fd->len); break; case SEEK_CUR: fd->pos = MIN( MAX( fd->pos + offset, 0 ), fd->len ); break;
case SEEK_END: fd->pos = MIN( MAX( fd->len + offset, 0 ), fd->len ); break;
} }
return 0; return 0;
@ -229,115 +245,123 @@ static s64 ntfs_device_gekko_io_seek(struct ntfs_device *dev, s64 offset, int wh
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_read(struct ntfs_device *dev, void *buf, s64 count) static s64 ntfs_device_gekko_io_read( struct ntfs_device *dev, void *buf, s64 count )
{ {
return ntfs_device_gekko_io_readbytes(dev, DEV_FD(dev)->pos, count, buf); return ntfs_device_gekko_io_readbytes( dev, DEV_FD( dev )->pos, count, buf );
} }
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_write(struct ntfs_device *dev, const void *buf, s64 count) static s64 ntfs_device_gekko_io_write( struct ntfs_device *dev, const void *buf, s64 count )
{ {
return ntfs_device_gekko_io_writebytes(dev, DEV_FD(dev)->pos, count, buf); return ntfs_device_gekko_io_writebytes( dev, DEV_FD( dev )->pos, count, buf );
} }
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_pread(struct ntfs_device *dev, void *buf, s64 count, s64 offset) static s64 ntfs_device_gekko_io_pread( struct ntfs_device *dev, void *buf, s64 count, s64 offset )
{ {
return ntfs_device_gekko_io_readbytes(dev, offset, count, buf); return ntfs_device_gekko_io_readbytes( dev, offset, count, buf );
} }
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_pwrite(struct ntfs_device *dev, const void *buf, s64 count, s64 offset) static s64 ntfs_device_gekko_io_pwrite( struct ntfs_device *dev, const void *buf, s64 count, s64 offset )
{ {
return ntfs_device_gekko_io_writebytes(dev, offset, count, buf); return ntfs_device_gekko_io_writebytes( dev, offset, count, buf );
} }
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s64 count, void *buf) static s64 ntfs_device_gekko_io_readbytes( struct ntfs_device *dev, s64 offset, s64 count, void *buf )
{ {
ntfs_log_trace("dev %p, offset %Li, count %Li\n", dev, offset, count); ntfs_log_trace( "dev %p, offset %Li, count %Li\n", dev, offset, count );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Get the device interface // Get the device interface
const DISC_INTERFACE* interface = fd->interface; const DISC_INTERFACE* interface = fd->interface;
if (!interface) { if ( !interface )
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
if(offset < 0) if ( offset < 0 )
{ {
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
if(!count) if ( !count )
return 0; return 0;
sec_t sec_start = (sec_t) fd->startSector; sec_t sec_start = ( sec_t ) fd->startSector;
sec_t sec_count = 1; sec_t sec_count = 1;
u32 buffer_offset = (u32) (offset % fd->sectorSize); u32 buffer_offset = ( u32 ) ( offset % fd->sectorSize );
u8 *buffer = NULL; u8 *buffer = NULL;
// Determine the range of sectors required for this read // Determine the range of sectors required for this read
if (offset > 0) { if ( offset > 0 )
sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize); {
sec_start += ( sec_t ) floor( ( f64 ) offset / ( f64 ) fd->sectorSize );
} }
if (buffer_offset+count > fd->sectorSize) { if ( buffer_offset + count > fd->sectorSize )
sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize); {
sec_count = ( sec_t ) ceil( ( f64 ) ( buffer_offset + count ) / ( f64 ) fd->sectorSize );
} }
// If this read happens to be on the sector boundaries then do the read straight into the destination buffer // If this read happens to be on the sector boundaries then do the read straight into the destination buffer
if((buffer_offset == 0) && (count % fd->sectorSize == 0)) { if ( ( buffer_offset == 0 ) && ( count % fd->sectorSize == 0 ) )
{
// Read from the device // Read from the device
ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace( "direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count );
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buf)) { if ( !ntfs_device_gekko_io_readsectors( dev, sec_start, sec_count, buf ) )
ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); {
ntfs_log_perror( "direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Else read into a buffer and copy over only what was requested // Else read into a buffer and copy over only what was requested
} }
else else
{ {
// Allocate a buffer to hold the read data // Allocate a buffer to hold the read data
buffer = (u8*)ntfs_alloc(sec_count * fd->sectorSize); buffer = ( u8* )ntfs_alloc( sec_count * fd->sectorSize );
if (!buffer) { if ( !buffer )
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
// Read from the device // Read from the device
ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace( "buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count );
ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize); ntfs_log_trace( "count: %d sec_count:%d fd->sectorSize: %d )\n", ( u32 )count, ( u32 )sec_count, ( u32 )fd->sectorSize );
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buffer)) { if ( !ntfs_device_gekko_io_readsectors( dev, sec_start, sec_count, buffer ) )
ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); {
ntfs_free(buffer); ntfs_log_perror( "buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count );
ntfs_free( buffer );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Copy what was requested to the destination buffer // Copy what was requested to the destination buffer
memcpy(buf, buffer + buffer_offset, count); memcpy( buf, buffer + buffer_offset, count );
ntfs_free(buffer); ntfs_free( buffer );
} }
@ -347,146 +371,159 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s
/** /**
* *
*/ */
static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset, s64 count, const void *buf) static s64 ntfs_device_gekko_io_writebytes( struct ntfs_device *dev, s64 offset, s64 count, const void *buf )
{ {
ntfs_log_trace("dev %p, offset %lli, count %lli\n", dev, offset, count); ntfs_log_trace( "dev %p, offset %lli, count %lli\n", dev, offset, count );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Get the device interface // Get the device interface
const DISC_INTERFACE* interface = fd->interface; const DISC_INTERFACE* interface = fd->interface;
if (!interface) { if ( !interface )
{
errno = ENODEV; errno = ENODEV;
return -1; return -1;
} }
// Check that the device can be written to // Check that the device can be written to
if (NDevReadOnly(dev)) { if ( NDevReadOnly( dev ) )
{
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
if(count < 0 || offset < 0) { if ( count < 0 || offset < 0 )
{
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
if(count == 0) if ( count == 0 )
return 0; return 0;
sec_t sec_start = (sec_t) fd->startSector; sec_t sec_start = ( sec_t ) fd->startSector;
sec_t sec_count = 1; sec_t sec_count = 1;
u32 buffer_offset = (u32) (offset % fd->sectorSize); u32 buffer_offset = ( u32 ) ( offset % fd->sectorSize );
u8 *buffer = NULL; u8 *buffer = NULL;
// Determine the range of sectors required for this write // Determine the range of sectors required for this write
if (offset > 0) { if ( offset > 0 )
sec_start += (sec_t) floor((f64) offset / (f64) fd->sectorSize); {
sec_start += ( sec_t ) floor( ( f64 ) offset / ( f64 ) fd->sectorSize );
} }
if ((buffer_offset+count) > fd->sectorSize) { if ( ( buffer_offset + count ) > fd->sectorSize )
sec_count = (sec_t) ceil((f64) (buffer_offset+count) / (f64) fd->sectorSize); {
sec_count = ( sec_t ) ceil( ( f64 ) ( buffer_offset + count ) / ( f64 ) fd->sectorSize );
} }
// If this write happens to be on the sector boundaries then do the write straight to disc // If this write happens to be on the sector boundaries then do the write straight to disc
if((buffer_offset == 0) && (count % fd->sectorSize == 0)) if ( ( buffer_offset == 0 ) && ( count % fd->sectorSize == 0 ) )
{ {
// Write to the device // Write to the device
ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace( "direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count );
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buf)) { if ( !ntfs_device_gekko_io_writesectors( dev, sec_start, sec_count, buf ) )
ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); {
ntfs_log_perror( "direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Else write from a buffer aligned to the sector boundaries // Else write from a buffer aligned to the sector boundaries
} }
else else
{ {
// Allocate a buffer to hold the write data // Allocate a buffer to hold the write data
buffer = (u8 *) ntfs_alloc(sec_count * fd->sectorSize); buffer = ( u8 * ) ntfs_alloc( sec_count * fd->sectorSize );
if (!buffer) { if ( !buffer )
{
errno = ENOMEM; errno = ENOMEM;
return -1; return -1;
} }
// Read the first and last sectors of the buffer from disc (if required) // Read the first and last sectors of the buffer from disc (if required)
// NOTE: This is done because the data does not line up with the sector boundaries, // NOTE: This is done because the data does not line up with the sector boundaries,
// we just read in the buffer edges where the data overlaps with the rest of the disc // we just read in the buffer edges where the data overlaps with the rest of the disc
if(buffer_offset != 0) if ( buffer_offset != 0 )
{ {
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) { if ( !ntfs_device_gekko_io_readsectors( dev, sec_start, 1, buffer ) )
ntfs_log_perror("read failure @ sector %d\n", sec_start); {
ntfs_free(buffer); ntfs_log_perror( "read failure @ sector %d\n", sec_start );
ntfs_free( buffer );
errno = EIO; errno = EIO;
return -1; return -1;
} }
} }
if((buffer_offset+count) % fd->sectorSize != 0) if ( ( buffer_offset + count ) % fd->sectorSize != 0 )
{ {
if (!ntfs_device_gekko_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) { if ( !ntfs_device_gekko_io_readsectors( dev, sec_start + sec_count - 1, 1, buffer + ( ( sec_count - 1 ) * fd->sectorSize ) ) )
ntfs_log_perror("read failure @ sector %d\n", sec_start + sec_count - 1); {
ntfs_free(buffer); ntfs_log_perror( "read failure @ sector %d\n", sec_start + sec_count - 1 );
ntfs_free( buffer );
errno = EIO; errno = EIO;
return -1; return -1;
} }
} }
// Copy the data into the write buffer // Copy the data into the write buffer
memcpy(buffer + buffer_offset, buf, count); memcpy( buffer + buffer_offset, buf, count );
// Write to the device // Write to the device
ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace( "buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count );
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buffer)) { if ( !ntfs_device_gekko_io_writesectors( dev, sec_start, sec_count, buffer ) )
ntfs_log_perror("buffered write failure @ sector %d\n", sec_start); {
ntfs_free(buffer); ntfs_log_perror( "buffered write failure @ sector %d\n", sec_start );
ntfs_free( buffer );
errno = EIO; errno = EIO;
return -1; return -1;
} }
// Free the buffer // Free the buffer
ntfs_free(buffer); ntfs_free( buffer );
} }
// Mark the device as dirty (if we actually wrote anything) // Mark the device as dirty (if we actually wrote anything)
NDevSetDirty(dev); NDevSetDirty( dev );
return count; return count;
} }
static bool ntfs_device_gekko_io_readsectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer) static bool ntfs_device_gekko_io_readsectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, void* buffer )
{ {
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return false; return false;
} }
// Read the sectors from disc (or cache, if enabled) // Read the sectors from disc (or cache, if enabled)
if (fd->cache) if ( fd->cache )
return _NTFS_cache_readSectors(fd->cache, sector, numSectors, buffer); return _NTFS_cache_readSectors( fd->cache, sector, numSectors, buffer );
else else
return fd->interface->readSectors(sector, numSectors, buffer); return fd->interface->readSectors( sector, numSectors, buffer );
return false; return false;
} }
static bool ntfs_device_gekko_io_writesectors(struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer) static bool ntfs_device_gekko_io_writesectors( struct ntfs_device *dev, sec_t sector, sec_t numSectors, const void* buffer )
{ {
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return false; return false;
} }
// Write the sectors to disc (or cache, if enabled) // Write the sectors to disc (or cache, if enabled)
if (fd->cache) if ( fd->cache )
return _NTFS_cache_writeSectors(fd->cache, sector, numSectors, buffer); return _NTFS_cache_writeSectors( fd->cache, sector, numSectors, buffer );
else else
return fd->interface->writeSectors(sector, numSectors, buffer); return fd->interface->writeSectors( sector, numSectors, buffer );
return false; return false;
} }
@ -494,23 +531,26 @@ static bool ntfs_device_gekko_io_writesectors(struct ntfs_device *dev, sec_t sec
/** /**
* *
*/ */
static int ntfs_device_gekko_io_sync(struct ntfs_device *dev) static int ntfs_device_gekko_io_sync( struct ntfs_device *dev )
{ {
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
ntfs_log_trace("dev %p\n", dev); ntfs_log_trace( "dev %p\n", dev );
// Check that the device can be written to // Check that the device can be written to
if (NDevReadOnly(dev)) { if ( NDevReadOnly( dev ) )
{
errno = EROFS; errno = EROFS;
return -1; return -1;
} }
// Mark the device as clean // Mark the device as clean
NDevClearDirty(dev); NDevClearDirty( dev );
// Flush any sectors in the disc cache (if required) // Flush any sectors in the disc cache (if required)
if (fd->cache) { if ( fd->cache )
if (!_NTFS_cache_flush(fd->cache)) { {
if ( !_NTFS_cache_flush( fd->cache ) )
{
errno = EIO; errno = EIO;
return -1; return -1;
} }
@ -522,28 +562,29 @@ static int ntfs_device_gekko_io_sync(struct ntfs_device *dev)
/** /**
* *
*/ */
static int ntfs_device_gekko_io_stat(struct ntfs_device *dev, struct stat *buf) static int ntfs_device_gekko_io_stat( struct ntfs_device *dev, struct stat *buf )
{ {
ntfs_log_trace("dev %p, buf %p\n", dev, buf); ntfs_log_trace( "dev %p, buf %p\n", dev, buf );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Short circuit cases were we don't actually have to do anything // Short circuit cases were we don't actually have to do anything
if (!buf) if ( !buf )
return 0; return 0;
// Build the device mode // Build the device mode
mode_t mode = (S_IFBLK) | mode_t mode = ( S_IFBLK ) |
(S_IRUSR | S_IRGRP | S_IROTH) | ( S_IRUSR | S_IRGRP | S_IROTH ) |
((!NDevReadOnly(dev)) ? (S_IWUSR | S_IWGRP | S_IWOTH) : 0); ( ( !NDevReadOnly( dev ) ) ? ( S_IWUSR | S_IWGRP | S_IWOTH ) : 0 );
// Zero out the stat buffer // Zero out the stat buffer
memset(buf, 0, sizeof(struct stat)); memset( buf, 0, sizeof( struct stat ) );
// Build the device stats // Build the device stats
buf->st_dev = fd->interface->ioType; buf->st_dev = fd->interface->ioType;
@ -559,71 +600,79 @@ static int ntfs_device_gekko_io_stat(struct ntfs_device *dev, struct stat *buf)
/** /**
* *
*/ */
static int ntfs_device_gekko_io_ioctl(struct ntfs_device *dev, int request, void *argp) static int ntfs_device_gekko_io_ioctl( struct ntfs_device *dev, int request, void *argp )
{ {
ntfs_log_trace("dev %p, request %i, argp %p\n", dev, request, argp); ntfs_log_trace( "dev %p, request %i, argp %p\n", dev, request, argp );
// Get the device driver descriptor // Get the device driver descriptor
gekko_fd *fd = DEV_FD(dev); gekko_fd *fd = DEV_FD( dev );
if (!fd) { if ( !fd )
{
errno = EBADF; errno = EBADF;
return -1; return -1;
} }
// Figure out which i/o control was requested // Figure out which i/o control was requested
switch (request) { switch ( request )
{
// Get block device size (sectors) // Get block device size (sectors)
#if defined(BLKGETSIZE) #if defined(BLKGETSIZE)
case BLKGETSIZE: { case BLKGETSIZE:
*(u32*)argp = fd->sectorCount; {
return 0; *( u32* )argp = fd->sectorCount;
} return 0;
#endif }
#endif
// Get block device size (bytes) // Get block device size (bytes)
#if defined(BLKGETSIZE64) #if defined(BLKGETSIZE64)
case BLKGETSIZE64: { case BLKGETSIZE64:
*(u64*)argp = (fd->sectorCount * fd->sectorSize); {
return 0; *( u64* )argp = ( fd->sectorCount * fd->sectorSize );
} return 0;
#endif }
#endif
// Get hard drive geometry // Get hard drive geometry
#if defined(HDIO_GETGEO) #if defined(HDIO_GETGEO)
case HDIO_GETGEO: { case HDIO_GETGEO:
struct hd_geometry *geo = (struct hd_geometry*)argp; {
geo->sectors = 0; struct hd_geometry *geo = ( struct hd_geometry* )argp;
geo->heads = 0; geo->sectors = 0;
geo->cylinders = 0; geo->heads = 0;
geo->start = fd->hiddenSectors; geo->cylinders = 0;
return -1; geo->start = fd->hiddenSectors;
} return -1;
#endif }
#endif
// Get block device sector size (bytes) // Get block device sector size (bytes)
#if defined(BLKSSZGET) #if defined(BLKSSZGET)
case BLKSSZGET: { case BLKSSZGET:
*(int*)argp = fd->sectorSize; {
return 0; *( int* )argp = fd->sectorSize;
} return 0;
#endif }
#endif
// Set block device block size (bytes) // Set block device block size (bytes)
#if defined(BLKBSZSET) #if defined(BLKBSZSET)
case BLKBSZSET: { case BLKBSZSET:
int sectorSize = *(int*)argp; {
fd->sectorSize = sectorSize; int sectorSize = *( int* )argp;
return 0; fd->sectorSize = sectorSize;
} return 0;
#endif }
#endif
// Unimplemented ioctrl // Unimplemented ioctrl
default: { default:
ntfs_log_perror("Unimplemented ioctrl %i\n", request); {
errno = EOPNOTSUPP; ntfs_log_perror( "Unimplemented ioctrl %i\n", request );
return -1; errno = EOPNOTSUPP;
} return -1;
}
} }
@ -633,7 +682,8 @@ static int ntfs_device_gekko_io_ioctl(struct ntfs_device *dev, int request, void
/** /**
* Device operations for working with gekko style devices and files. * Device operations for working with gekko style devices and files.
*/ */
struct ntfs_device_operations ntfs_device_gekko_io_ops = { struct ntfs_device_operations ntfs_device_gekko_io_ops =
{
.open = ntfs_device_gekko_io_open, .open = ntfs_device_gekko_io_open,
.close = ntfs_device_gekko_io_close, .close = ntfs_device_gekko_io_close,
.seek = ntfs_device_gekko_io_seek, .seek = ntfs_device_gekko_io_seek,

Some files were not shown because too many files have changed in this diff Show More