2005-04-17 02:20:36 +04:00
/*
* linux / fs / hpfs / map . c
*
* Mikulas Patocka ( mikulas @ artax . karlin . mff . cuni . cz ) , 1998 - 1999
*
* mapping structures to memory with some minimal checks
*/
# include "hpfs_fn.h"
unsigned * hpfs_map_dnode_bitmap ( struct super_block * s , struct quad_buffer_head * qbh )
{
return hpfs_map_4sectors ( s , hpfs_sb ( s ) - > sb_dmap , qbh , 0 ) ;
}
unsigned int * hpfs_map_bitmap ( struct super_block * s , unsigned bmp_block ,
struct quad_buffer_head * qbh , char * id )
{
secno sec ;
if ( hpfs_sb ( s ) - > sb_chk ) if ( bmp_block * 16384 > hpfs_sb ( s ) - > sb_fs_size ) {
hpfs_error ( s , " hpfs_map_bitmap called with bad parameter: %08x at %s " , bmp_block , id ) ;
return NULL ;
}
sec = hpfs_sb ( s ) - > sb_bmp_dir [ bmp_block ] ;
if ( ! sec | | sec > hpfs_sb ( s ) - > sb_fs_size - 4 ) {
hpfs_error ( s , " invalid bitmap block pointer %08x -> %08x at %s " , bmp_block , sec , id ) ;
return NULL ;
}
return hpfs_map_4sectors ( s , sec , qbh , 4 ) ;
}
/*
* Load first code page into kernel memory , return pointer to 256 - byte array ,
* first 128 bytes are uppercasing table for chars 128 - 255 , next 128 bytes are
* lowercasing table
*/
char * hpfs_load_code_page ( struct super_block * s , secno cps )
{
struct buffer_head * bh ;
secno cpds ;
unsigned cpi ;
unsigned char * ptr ;
unsigned char * cp_table ;
int i ;
struct code_page_data * cpd ;
struct code_page_directory * cp = hpfs_map_sector ( s , cps , & bh , 0 ) ;
if ( ! cp ) return NULL ;
if ( cp - > magic ! = CP_DIR_MAGIC ) {
printk ( " HPFS: Code page directory magic doesn't match (magic = %08x) \n " , cp - > magic ) ;
brelse ( bh ) ;
return NULL ;
}
if ( ! cp - > n_code_pages ) {
printk ( " HPFS: n_code_pages == 0 \n " ) ;
brelse ( bh ) ;
return NULL ;
}
cpds = cp - > array [ 0 ] . code_page_data ;
cpi = cp - > array [ 0 ] . index ;
brelse ( bh ) ;
if ( cpi > = 3 ) {
printk ( " HPFS: Code page index out of array \n " ) ;
return NULL ;
}
if ( ! ( cpd = hpfs_map_sector ( s , cpds , & bh , 0 ) ) ) return NULL ;
if ( ( unsigned ) cpd - > offs [ cpi ] > 0x178 ) {
printk ( " HPFS: Code page index out of sector \n " ) ;
brelse ( bh ) ;
return NULL ;
}
ptr = ( char * ) cpd + cpd - > offs [ cpi ] + 6 ;
if ( ! ( cp_table = kmalloc ( 256 , GFP_KERNEL ) ) ) {
printk ( " HPFS: out of memory for code page table \n " ) ;
brelse ( bh ) ;
return NULL ;
}
memcpy ( cp_table , ptr , 128 ) ;
brelse ( bh ) ;
/* Try to build lowercasing table from uppercasing one */
for ( i = 128 ; i < 256 ; i + + ) cp_table [ i ] = i ;
for ( i = 128 ; i < 256 ; i + + ) if ( cp_table [ i - 128 ] ! = i & & cp_table [ i - 128 ] > = 128 )
cp_table [ cp_table [ i - 128 ] ] = i ;
return cp_table ;
}
secno * hpfs_load_bitmap_directory ( struct super_block * s , secno bmp )
{
struct buffer_head * bh ;
int n = ( hpfs_sb ( s ) - > sb_fs_size + 0x200000 - 1 ) > > 21 ;
int i ;
secno * b ;
if ( ! ( b = kmalloc ( n * 512 , GFP_KERNEL ) ) ) {
printk ( " HPFS: can't allocate memory for bitmap directory \n " ) ;
return NULL ;
}
for ( i = 0 ; i < n ; i + + ) {
secno * d = hpfs_map_sector ( s , bmp + i , & bh , n - i - 1 ) ;
if ( ! d ) {
kfree ( b ) ;
return NULL ;
}
memcpy ( ( char * ) b + 512 * i , d , 512 ) ;
brelse ( bh ) ;
}
return b ;
}
/*
* Load fnode to memory
*/
struct fnode * hpfs_map_fnode ( struct super_block * s , ino_t ino , struct buffer_head * * bhp )
{
struct fnode * fnode ;
if ( hpfs_sb ( s ) - > sb_chk ) if ( hpfs_chk_sectors ( s , ino , 1 , " fnode " ) ) {
return NULL ;
}
if ( ( fnode = hpfs_map_sector ( s , ino , bhp , FNODE_RD_AHEAD ) ) ) {
if ( hpfs_sb ( s ) - > sb_chk ) {
struct extended_attribute * ea ;
struct extended_attribute * ea_end ;
if ( fnode - > magic ! = FNODE_MAGIC ) {
[PATCH] hpfs: fix printk format warnings
Fix hpfs printk warnings:
fs/hpfs/dir.c:87: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/dir.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dir.c:148: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dnode.c:537: warning: format '%08x' expects type 'unsigned int', but argument 5 has type 'long unsigned int'
fs/hpfs/dnode.c:854: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'loff_t'
fs/hpfs/ea.c:247: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/inode.c:254: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/map.c:129: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:135: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:140: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:154: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 07:37:05 +03:00
hpfs_error ( s , " bad magic on fnode %08lx " ,
( unsigned long ) ino ) ;
2005-04-17 02:20:36 +04:00
goto bail ;
}
if ( ! fnode - > dirflag ) {
if ( ( unsigned ) fnode - > btree . n_used_nodes + ( unsigned ) fnode - > btree . n_free_nodes ! =
( fnode - > btree . internal ? 12 : 8 ) ) {
[PATCH] hpfs: fix printk format warnings
Fix hpfs printk warnings:
fs/hpfs/dir.c:87: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/dir.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dir.c:148: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dnode.c:537: warning: format '%08x' expects type 'unsigned int', but argument 5 has type 'long unsigned int'
fs/hpfs/dnode.c:854: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'loff_t'
fs/hpfs/ea.c:247: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/inode.c:254: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/map.c:129: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:135: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:140: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:154: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 07:37:05 +03:00
hpfs_error ( s ,
" bad number of nodes in fnode %08lx " ,
( unsigned long ) ino ) ;
2005-04-17 02:20:36 +04:00
goto bail ;
}
if ( fnode - > btree . first_free ! =
8 + fnode - > btree . n_used_nodes * ( fnode - > btree . internal ? 8 : 12 ) ) {
[PATCH] hpfs: fix printk format warnings
Fix hpfs printk warnings:
fs/hpfs/dir.c:87: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/dir.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dir.c:148: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dnode.c:537: warning: format '%08x' expects type 'unsigned int', but argument 5 has type 'long unsigned int'
fs/hpfs/dnode.c:854: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'loff_t'
fs/hpfs/ea.c:247: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/inode.c:254: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/map.c:129: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:135: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:140: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:154: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 07:37:05 +03:00
hpfs_error ( s ,
" bad first_free pointer in fnode %08lx " ,
( unsigned long ) ino ) ;
2005-04-17 02:20:36 +04:00
goto bail ;
}
}
if ( fnode - > ea_size_s & & ( ( signed int ) fnode - > ea_offs < 0xc4 | |
( signed int ) fnode - > ea_offs + fnode - > acl_size_s + fnode - > ea_size_s > 0x200 ) ) {
[PATCH] hpfs: fix printk format warnings
Fix hpfs printk warnings:
fs/hpfs/dir.c:87: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/dir.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dir.c:148: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dnode.c:537: warning: format '%08x' expects type 'unsigned int', but argument 5 has type 'long unsigned int'
fs/hpfs/dnode.c:854: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'loff_t'
fs/hpfs/ea.c:247: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/inode.c:254: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/map.c:129: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:135: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:140: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:154: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 07:37:05 +03:00
hpfs_error ( s ,
" bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x " ,
( unsigned long ) ino ,
fnode - > ea_offs , fnode - > ea_size_s ) ;
2005-04-17 02:20:36 +04:00
goto bail ;
}
ea = fnode_ea ( fnode ) ;
ea_end = fnode_end_ea ( fnode ) ;
while ( ea ! = ea_end ) {
if ( ea > ea_end ) {
[PATCH] hpfs: fix printk format warnings
Fix hpfs printk warnings:
fs/hpfs/dir.c:87: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/dir.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dir.c:148: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long int'
fs/hpfs/dnode.c:537: warning: format '%08x' expects type 'unsigned int', but argument 5 has type 'long unsigned int'
fs/hpfs/dnode.c:854: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'loff_t'
fs/hpfs/ea.c:247: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/inode.c:254: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'long unsigned int'
fs/hpfs/map.c:129: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:135: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:140: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:147: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
fs/hpfs/map.c:154: warning: format '%08x' expects type 'unsigned int', but argument 3 has type 'ino_t'
Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-12-07 07:37:05 +03:00
hpfs_error ( s , " bad EA in fnode %08lx " ,
( unsigned long ) ino ) ;
2005-04-17 02:20:36 +04:00
goto bail ;
}
ea = next_ea ( ea ) ;
}
}
}
return fnode ;
bail :
brelse ( * bhp ) ;
return NULL ;
}
struct anode * hpfs_map_anode ( struct super_block * s , anode_secno ano , struct buffer_head * * bhp )
{
struct anode * anode ;
if ( hpfs_sb ( s ) - > sb_chk ) if ( hpfs_chk_sectors ( s , ano , 1 , " anode " ) ) return NULL ;
if ( ( anode = hpfs_map_sector ( s , ano , bhp , ANODE_RD_AHEAD ) ) )
if ( hpfs_sb ( s ) - > sb_chk ) {
if ( anode - > magic ! = ANODE_MAGIC | | anode - > self ! = ano ) {
hpfs_error ( s , " bad magic on anode %08x " , ano ) ;
goto bail ;
}
if ( ( unsigned ) anode - > btree . n_used_nodes + ( unsigned ) anode - > btree . n_free_nodes ! =
( anode - > btree . internal ? 60 : 40 ) ) {
hpfs_error ( s , " bad number of nodes in anode %08x " , ano ) ;
goto bail ;
}
if ( anode - > btree . first_free ! =
8 + anode - > btree . n_used_nodes * ( anode - > btree . internal ? 8 : 12 ) ) {
hpfs_error ( s , " bad first_free pointer in anode %08x " , ano ) ;
goto bail ;
}
}
return anode ;
bail :
brelse ( * bhp ) ;
return NULL ;
}
/*
* Load dnode to memory and do some checks
*/
struct dnode * hpfs_map_dnode ( struct super_block * s , unsigned secno ,
struct quad_buffer_head * qbh )
{
struct dnode * dnode ;
if ( hpfs_sb ( s ) - > sb_chk ) {
if ( hpfs_chk_sectors ( s , secno , 4 , " dnode " ) ) return NULL ;
if ( secno & 3 ) {
hpfs_error ( s , " dnode %08x not byte-aligned " , secno ) ;
return NULL ;
}
}
if ( ( dnode = hpfs_map_4sectors ( s , secno , qbh , DNODE_RD_AHEAD ) ) )
if ( hpfs_sb ( s ) - > sb_chk ) {
unsigned p , pp = 0 ;
unsigned char * d = ( char * ) dnode ;
int b = 0 ;
if ( dnode - > magic ! = DNODE_MAGIC ) {
hpfs_error ( s , " bad magic on dnode %08x " , secno ) ;
goto bail ;
}
if ( dnode - > self ! = secno )
hpfs_error ( s , " bad self pointer on dnode %08x self = %08x " , secno , dnode - > self ) ;
/* Check dirents - bad dirents would cause infinite
loops or shooting to memory */
if ( dnode - > first_free > 2048 /* || dnode->first_free < 84*/ ) {
hpfs_error ( s , " dnode %08x has first_free == %08x " , secno , dnode - > first_free ) ;
goto bail ;
}
for ( p = 20 ; p < dnode - > first_free ; p + = d [ p ] + ( d [ p + 1 ] < < 8 ) ) {
struct hpfs_dirent * de = ( struct hpfs_dirent * ) ( ( char * ) dnode + p ) ;
if ( de - > length > 292 | | ( de - > length < 32 ) | | ( de - > length & 3 ) | | p + de - > length > 2048 ) {
hpfs_error ( s , " bad dirent size in dnode %08x, dirent %03x, last %03x " , secno , p , pp ) ;
goto bail ;
}
if ( ( ( 31 + de - > namelen + de - > down * 4 + 3 ) & ~ 3 ) ! = de - > length ) {
if ( ( ( 31 + de - > namelen + de - > down * 4 + 3 ) & ~ 3 ) < de - > length & & s - > s_flags & MS_RDONLY ) goto ok ;
hpfs_error ( s , " namelen does not match dirent size in dnode %08x, dirent %03x, last %03x " , secno , p , pp ) ;
goto bail ;
}
ok :
if ( hpfs_sb ( s ) - > sb_chk > = 2 ) b | = 1 < < de - > down ;
if ( de - > down ) if ( de_down_pointer ( de ) < 0x10 ) {
hpfs_error ( s , " bad down pointer in dnode %08x, dirent %03x, last %03x " , secno , p , pp ) ;
goto bail ;
}
pp = p ;
}
if ( p ! = dnode - > first_free ) {
hpfs_error ( s , " size on last dirent does not match first_free; dnode %08x " , secno ) ;
goto bail ;
}
if ( d [ pp + 30 ] ! = 1 | | d [ pp + 31 ] ! = 255 ) {
hpfs_error ( s , " dnode %08x does not end with \\ 377 entry " , secno ) ;
goto bail ;
}
if ( b = = 3 ) printk ( " HPFS: warning: unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info \n " , secno ) ;
}
return dnode ;
bail :
hpfs_brelse4 ( qbh ) ;
return NULL ;
}
dnode_secno hpfs_fnode_dno ( struct super_block * s , ino_t ino )
{
struct buffer_head * bh ;
struct fnode * fnode ;
dnode_secno dno ;
fnode = hpfs_map_fnode ( s , ino , & bh ) ;
if ( ! fnode )
return 0 ;
dno = fnode - > u . external [ 0 ] . disk_secno ;
brelse ( bh ) ;
return dno ;
}