Commit 7f4238a0 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'hpfs'

* hpfs:
  HPFS: Remove unused variable
  HPFS: Move declaration up, so that there are no out-of-scope pointers
  HPFS: Fix some unaligned accesses
  HPFS: Fix endianity. Make hpfs work on big-endian machines
  HPFS: Implement fsync for hpfs
  HPFS: Fix a bug that filesystem was not marked dirty when remounting it
  HPFS: Restrict uid and gid to 16-bit values
  HPFS: When marking or clearing the dirty bit, sync the filesystem
  HPFS: Use types with defined width
  HPFS: Remove mark_inode_dirty
  HPFS: Remove CR/LF conversion option
  HPFS: Remove remaining locks
  HPFS: Introduce a global mutex and lock it on every callback from VFS.
  HPFS: Make HPFS compile on preempt and SMP
parents 8b061610 88f4e9e8
config HPFS_FS config HPFS_FS
tristate "OS/2 HPFS file system support" tristate "OS/2 HPFS file system support"
depends on BLOCK depends on BLOCK
depends on BROKEN || !PREEMPT
help help
OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS OS/2 is IBM's operating system for PC's, the same as Warp, and HPFS
is the file system used for organizing files on OS/2 hard disk is the file system used for organizing files on OS/2 hard disk
......
This diff is collapsed.
This diff is collapsed.
...@@ -9,22 +9,6 @@ ...@@ -9,22 +9,6 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "hpfs_fn.h" #include "hpfs_fn.h"
void hpfs_lock_creation(struct super_block *s)
{
#ifdef DEBUG_LOCKS
printk("lock creation\n");
#endif
mutex_lock(&hpfs_sb(s)->hpfs_creation_de);
}
void hpfs_unlock_creation(struct super_block *s)
{
#ifdef DEBUG_LOCKS
printk("unlock creation\n");
#endif
mutex_unlock(&hpfs_sb(s)->hpfs_creation_de);
}
/* Map a sector into a buffer and return pointers to it and to the buffer. */ /* Map a sector into a buffer and return pointers to it and to the buffer. */
void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp, void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
...@@ -32,6 +16,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head ...@@ -32,6 +16,8 @@ void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head
{ {
struct buffer_head *bh; struct buffer_head *bh;
hpfs_lock_assert(s);
cond_resched(); cond_resched();
*bhp = bh = sb_bread(s, secno); *bhp = bh = sb_bread(s, secno);
...@@ -50,6 +36,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head ...@@ -50,6 +36,8 @@ void *hpfs_get_sector(struct super_block *s, unsigned secno, struct buffer_head
struct buffer_head *bh; struct buffer_head *bh;
/*return hpfs_map_sector(s, secno, bhp, 0);*/ /*return hpfs_map_sector(s, secno, bhp, 0);*/
hpfs_lock_assert(s);
cond_resched(); cond_resched();
if ((*bhp = bh = sb_getblk(s, secno)) != NULL) { if ((*bhp = bh = sb_getblk(s, secno)) != NULL) {
...@@ -70,6 +58,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe ...@@ -70,6 +58,8 @@ void *hpfs_map_4sectors(struct super_block *s, unsigned secno, struct quad_buffe
struct buffer_head *bh; struct buffer_head *bh;
char *data; char *data;
hpfs_lock_assert(s);
cond_resched(); cond_resched();
if (secno & 3) { if (secno & 3) {
...@@ -125,6 +115,8 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno, ...@@ -125,6 +115,8 @@ void *hpfs_get_4sectors(struct super_block *s, unsigned secno,
{ {
cond_resched(); cond_resched();
hpfs_lock_assert(s);
if (secno & 3) { if (secno & 3) {
printk("HPFS: hpfs_get_4sectors: unaligned read\n"); printk("HPFS: hpfs_get_4sectors: unaligned read\n");
return NULL; return NULL;
......
...@@ -88,9 +88,9 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -88,9 +88,9 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
hpfs_error(inode->i_sb, "not a directory, fnode %08lx", hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
(unsigned long)inode->i_ino); (unsigned long)inode->i_ino);
} }
if (hpfs_inode->i_dno != fno->u.external[0].disk_secno) { if (hpfs_inode->i_dno != le32_to_cpu(fno->u.external[0].disk_secno)) {
e = 1; e = 1;
hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, fno->u.external[0].disk_secno); hpfs_error(inode->i_sb, "corrupted inode: i_dno == %08x, fnode -> dnode == %08x", hpfs_inode->i_dno, le32_to_cpu(fno->u.external[0].disk_secno));
} }
brelse(bh); brelse(bh);
if (e) { if (e) {
...@@ -156,7 +156,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -156,7 +156,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto again; goto again;
} }
tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3); tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) { if (filldir(dirent, tempname, de->namelen, old_pos, le32_to_cpu(de->fnode), DT_UNKNOWN) < 0) {
filp->f_pos = old_pos; filp->f_pos = old_pos;
if (tempname != de->name) kfree(tempname); if (tempname != de->name) kfree(tempname);
hpfs_brelse4(&qbh); hpfs_brelse4(&qbh);
...@@ -221,7 +221,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name ...@@ -221,7 +221,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
* Get inode number, what we're after. * Get inode number, what we're after.
*/ */
ino = de->fnode; ino = le32_to_cpu(de->fnode);
/* /*
* Go find or make an inode. * Go find or make an inode.
...@@ -236,7 +236,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name ...@@ -236,7 +236,7 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
hpfs_init_inode(result); hpfs_init_inode(result);
if (de->directory) if (de->directory)
hpfs_read_inode(result); hpfs_read_inode(result);
else if (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas) else if (le32_to_cpu(de->ea_size) && hpfs_sb(dir->i_sb)->sb_eas)
hpfs_read_inode(result); hpfs_read_inode(result);
else { else {
result->i_mode |= S_IFREG; result->i_mode |= S_IFREG;
...@@ -250,8 +250,6 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name ...@@ -250,8 +250,6 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
hpfs_result = hpfs_i(result); hpfs_result = hpfs_i(result);
if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino; if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
hpfs_decide_conv(result, name, len);
if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) { if (de->has_acl || de->has_xtd_perm) if (!(dir->i_sb->s_flags & MS_RDONLY)) {
hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures"); hpfs_error(result->i_sb, "ACLs or XPERM found. This is probably HPFS386. This driver doesn't support it now. Send me some info on these structures");
goto bail1; goto bail1;
...@@ -263,19 +261,19 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name ...@@ -263,19 +261,19 @@ struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct name
*/ */
if (!result->i_ctime.tv_sec) { if (!result->i_ctime.tv_sec) {
if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, de->creation_date))) if (!(result->i_ctime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->creation_date))))
result->i_ctime.tv_sec = 1; result->i_ctime.tv_sec = 1;
result->i_ctime.tv_nsec = 0; result->i_ctime.tv_nsec = 0;
result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, de->write_date); result->i_mtime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->write_date));
result->i_mtime.tv_nsec = 0; result->i_mtime.tv_nsec = 0;
result->i_atime.tv_sec = local_to_gmt(dir->i_sb, de->read_date); result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(de->read_date));
result->i_atime.tv_nsec = 0; result->i_atime.tv_nsec = 0;
hpfs_result->i_ea_size = de->ea_size; hpfs_result->i_ea_size = le32_to_cpu(de->ea_size);
if (!hpfs_result->i_ea_mode && de->read_only) if (!hpfs_result->i_ea_mode && de->read_only)
result->i_mode &= ~0222; result->i_mode &= ~0222;
if (!de->directory) { if (!de->directory) {
if (result->i_size == -1) { if (result->i_size == -1) {
result->i_size = de->file_size; result->i_size = le32_to_cpu(de->file_size);
result->i_data.a_ops = &hpfs_aops; result->i_data.a_ops = &hpfs_aops;
hpfs_i(result)->mmu_private = result->i_size; hpfs_i(result)->mmu_private = result->i_size;
/* /*
......
This diff is collapsed.
This diff is collapsed.
...@@ -20,8 +20,8 @@ static int hpfs_file_release(struct inode *inode, struct file *file) ...@@ -20,8 +20,8 @@ static int hpfs_file_release(struct inode *inode, struct file *file)
int hpfs_file_fsync(struct file *file, int datasync) int hpfs_file_fsync(struct file *file, int datasync)
{ {
/*return file_fsync(file, datasync);*/ struct inode *inode = file->f_mapping->host;
return 0; /* Don't fsync :-) */ return sync_blockdev(inode->i_sb->s_bdev);
} }
/* /*
...@@ -48,38 +48,46 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno) ...@@ -48,38 +48,46 @@ static secno hpfs_bmap(struct inode *inode, unsigned file_secno)
static void hpfs_truncate(struct inode *i) static void hpfs_truncate(struct inode *i)
{ {
if (IS_IMMUTABLE(i)) return /*-EPERM*/; if (IS_IMMUTABLE(i)) return /*-EPERM*/;
hpfs_lock(i->i_sb); hpfs_lock_assert(i->i_sb);
hpfs_i(i)->i_n_secs = 0; hpfs_i(i)->i_n_secs = 0;
i->i_blocks = 1 + ((i->i_size + 511) >> 9); i->i_blocks = 1 + ((i->i_size + 511) >> 9);
hpfs_i(i)->mmu_private = i->i_size; hpfs_i(i)->mmu_private = i->i_size;
hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9)); hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
hpfs_write_inode(i); hpfs_write_inode(i);
hpfs_i(i)->i_n_secs = 0; hpfs_i(i)->i_n_secs = 0;
hpfs_unlock(i->i_sb);
} }
static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create) static int hpfs_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
{ {
int r;
secno s; secno s;
hpfs_lock(inode->i_sb);
s = hpfs_bmap(inode, iblock); s = hpfs_bmap(inode, iblock);
if (s) { if (s) {
map_bh(bh_result, inode->i_sb, s); map_bh(bh_result, inode->i_sb, s);
return 0; goto ret_0;
} }
if (!create) return 0; if (!create) goto ret_0;
if (iblock<<9 != hpfs_i(inode)->mmu_private) { if (iblock<<9 != hpfs_i(inode)->mmu_private) {
BUG(); BUG();
return -EIO; r = -EIO;
goto ret_r;
} }
if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) { if ((s = hpfs_add_sector_to_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1)) == -1) {
hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1); hpfs_truncate_btree(inode->i_sb, inode->i_ino, 1, inode->i_blocks - 1);
return -ENOSPC; r = -ENOSPC;
goto ret_r;
} }
inode->i_blocks++; inode->i_blocks++;
hpfs_i(inode)->mmu_private += 512; hpfs_i(inode)->mmu_private += 512;
set_buffer_new(bh_result); set_buffer_new(bh_result);
map_bh(bh_result, inode->i_sb, s); map_bh(bh_result, inode->i_sb, s);
return 0; ret_0:
r = 0;
ret_r:
hpfs_unlock(inode->i_sb);
return r;
} }
static int hpfs_writepage(struct page *page, struct writeback_control *wbc) static int hpfs_writepage(struct page *page, struct writeback_control *wbc)
...@@ -130,8 +138,11 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf, ...@@ -130,8 +138,11 @@ static ssize_t hpfs_file_write(struct file *file, const char __user *buf,
ssize_t retval; ssize_t retval;
retval = do_sync_write(file, buf, count, ppos); retval = do_sync_write(file, buf, count, ppos);
if (retval > 0) if (retval > 0) {
hpfs_lock(file->f_path.dentry->d_sb);
hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1; hpfs_i(file->f_path.dentry->d_inode)->i_dirty = 1;
hpfs_unlock(file->f_path.dentry->d_sb);
}
return retval; return retval;
} }
......
This diff is collapsed.
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/unaligned.h>
#include "hpfs.h" #include "hpfs.h"
...@@ -51,18 +52,16 @@ struct hpfs_inode_info { ...@@ -51,18 +52,16 @@ struct hpfs_inode_info {
unsigned i_disk_sec; /* (files) minimalist cache of alloc info */ unsigned i_disk_sec; /* (files) minimalist cache of alloc info */
unsigned i_n_secs; /* (files) minimalist cache of alloc info */ unsigned i_n_secs; /* (files) minimalist cache of alloc info */
unsigned i_ea_size; /* size of extended attributes */ unsigned i_ea_size; /* size of extended attributes */
unsigned i_conv : 2; /* (files) crlf->newline hackery */
unsigned i_ea_mode : 1; /* file's permission is stored in ea */ unsigned i_ea_mode : 1; /* file's permission is stored in ea */
unsigned i_ea_uid : 1; /* file's uid is stored in ea */ unsigned i_ea_uid : 1; /* file's uid is stored in ea */
unsigned i_ea_gid : 1; /* file's gid is stored in ea */ unsigned i_ea_gid : 1; /* file's gid is stored in ea */
unsigned i_dirty : 1; unsigned i_dirty : 1;
struct mutex i_mutex;
struct mutex i_parent_mutex;
loff_t **i_rddir_off; loff_t **i_rddir_off;
struct inode vfs_inode; struct inode vfs_inode;
}; };
struct hpfs_sb_info { struct hpfs_sb_info {
struct mutex hpfs_mutex; /* global hpfs lock */
ino_t sb_root; /* inode number of root dir */ ino_t sb_root; /* inode number of root dir */
unsigned sb_fs_size; /* file system size, sectors */ unsigned sb_fs_size; /* file system size, sectors */
unsigned sb_bitmaps; /* sector number of bitmap list */ unsigned sb_bitmaps; /* sector number of bitmap list */
...@@ -74,7 +73,6 @@ struct hpfs_sb_info { ...@@ -74,7 +73,6 @@ struct hpfs_sb_info {
uid_t sb_uid; /* uid from mount options */ uid_t sb_uid; /* uid from mount options */
gid_t sb_gid; /* gid from mount options */ gid_t sb_gid; /* gid from mount options */
umode_t sb_mode; /* mode from mount options */ umode_t sb_mode; /* mode from mount options */
unsigned sb_conv : 2; /* crlf->newline hackery */
unsigned sb_eas : 2; /* eas: 0-ignore, 1-ro, 2-rw */ unsigned sb_eas : 2; /* eas: 0-ignore, 1-ro, 2-rw */
unsigned sb_err : 2; /* on errs: 0-cont, 1-ro, 2-panic */ unsigned sb_err : 2; /* on errs: 0-cont, 1-ro, 2-panic */
unsigned sb_chk : 2; /* checks: 0-no, 1-normal, 2-strict */ unsigned sb_chk : 2; /* checks: 0-no, 1-normal, 2-strict */
...@@ -87,20 +85,9 @@ struct hpfs_sb_info { ...@@ -87,20 +85,9 @@ struct hpfs_sb_info {
unsigned *sb_bmp_dir; /* main bitmap directory */ unsigned *sb_bmp_dir; /* main bitmap directory */
unsigned sb_c_bitmap; /* current bitmap */ unsigned sb_c_bitmap; /* current bitmap */
unsigned sb_max_fwd_alloc; /* max forwad allocation */ unsigned sb_max_fwd_alloc; /* max forwad allocation */
struct mutex hpfs_creation_de; /* when creating dirents, nobody else
can alloc blocks */
/*unsigned sb_mounting : 1;*/
int sb_timeshift; int sb_timeshift;
}; };
/*
* conv= options
*/
#define CONV_BINARY 0 /* no conversion */
#define CONV_TEXT 1 /* crlf->newline */
#define CONV_AUTO 2 /* decide based on file contents */
/* Four 512-byte buffers and the 2k block obtained by concatenating them */ /* Four 512-byte buffers and the 2k block obtained by concatenating them */
struct quad_buffer_head { struct quad_buffer_head {
...@@ -113,7 +100,7 @@ struct quad_buffer_head { ...@@ -113,7 +100,7 @@ struct quad_buffer_head {
static inline dnode_secno de_down_pointer (struct hpfs_dirent *de) static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
{ {
CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n")); CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n"));
return *(dnode_secno *) ((void *) de + de->length - 4); return le32_to_cpu(*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4));
} }
/* The first dir entry in a dnode */ /* The first dir entry in a dnode */
...@@ -127,41 +114,46 @@ static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode) ...@@ -127,41 +114,46 @@ static inline struct hpfs_dirent *dnode_first_de (struct dnode *dnode)
static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode) static inline struct hpfs_dirent *dnode_end_de (struct dnode *dnode)
{ {
CHKCOND(dnode->first_free>=0x14 && dnode->first_free<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %d\n",(int)dnode->first_free)); CHKCOND(le32_to_cpu(dnode->first_free)>=0x14 && le32_to_cpu(dnode->first_free)<=0xa00,("HPFS: dnode_end_de: dnode->first_free = %x\n",(unsigned)le32_to_cpu(dnode->first_free)));
return (void *) dnode + dnode->first_free; return (void *) dnode + le32_to_cpu(dnode->first_free);
} }
/* The dir entry after dir entry de */ /* The dir entry after dir entry de */
static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de) static inline struct hpfs_dirent *de_next_de (struct hpfs_dirent *de)
{ {
CHKCOND(de->length>=0x20 && de->length<0x800,("HPFS: de_next_de: de->length = %d\n",(int)de->length)); CHKCOND(le16_to_cpu(de->length)>=0x20 && le16_to_cpu(de->length)<0x800,("HPFS: de_next_de: de->length = %x\n",(unsigned)le16_to_cpu(de->length)));
return (void *) de + de->length; return (void *) de + le16_to_cpu(de->length);
} }
static inline struct extended_attribute *fnode_ea(struct fnode *fnode) static inline struct extended_attribute *fnode_ea(struct fnode *fnode)
{ {
return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s); return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s));
} }
static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode) static inline struct extended_attribute *fnode_end_ea(struct fnode *fnode)
{ {
return (struct extended_attribute *)((char *)fnode + fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s); return (struct extended_attribute *)((char *)fnode + le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s));
}
static unsigned ea_valuelen(struct extended_attribute *ea)
{
return ea->valuelen_lo + 256 * ea->valuelen_hi;
} }
static inline struct extended_attribute *next_ea(struct extended_attribute *ea) static inline struct extended_attribute *next_ea(struct extended_attribute *ea)
{ {
return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea->valuelen); return (struct extended_attribute *)((char *)ea + 5 + ea->namelen + ea_valuelen(ea));
} }
static inline secno ea_sec(struct extended_attribute *ea) static inline secno ea_sec(struct extended_attribute *ea)
{ {
return *(secno *)((char *)ea + 9 + ea->namelen); return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen)));
} }
static inline secno ea_len(struct extended_attribute *ea) static inline secno ea_len(struct extended_attribute *ea)
{ {
return *(secno *)((char *)ea + 5 + ea->namelen); return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen)));
} }
static inline char *ea_data(struct extended_attribute *ea) static inline char *ea_data(struct extended_attribute *ea)
...@@ -186,13 +178,13 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src) ...@@ -186,13 +178,13 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)
dst->not_8x3 = n; dst->not_8x3 = n;
} }
static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n) static inline unsigned tstbits(u32 *bmp, unsigned b, unsigned n)
{ {
int i; int i;
if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n; if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
if (!((bmp[(b & 0x3fff) >> 5] >> (b & 0x1f)) & 1)) return 1; if (!((le32_to_cpu(bmp[(b & 0x3fff) >> 5]) >> (b & 0x1f)) & 1)) return 1;
for (i = 1; i < n; i++) for (i = 1; i < n; i++)
if (/*b+i < 0x4000 &&*/ !((bmp[((b+i) & 0x3fff) >> 5] >> ((b+i) & 0x1f)) & 1)) if (!((le32_to_cpu(bmp[((b+i) & 0x3fff) >> 5]) >> ((b+i) & 0x1f)) & 1))
return i + 1; return i + 1;
return 0; return 0;
} }
...@@ -200,12 +192,12 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n) ...@@ -200,12 +192,12 @@ static inline unsigned tstbits(unsigned *bmp, unsigned b, unsigned n)
/* alloc.c */ /* alloc.c */
int hpfs_chk_sectors(struct super_block *, secno, int, char *); int hpfs_chk_sectors(struct super_block *, secno, int, char *);
secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int, int); secno hpfs_alloc_sector(struct super_block *, secno, unsigned, int);
int hpfs_alloc_if_possible(struct super_block *, secno); int hpfs_alloc_if_possible(struct super_block *, secno);
void hpfs_free_sectors(struct super_block *, secno, unsigned); void hpfs_free_sectors(struct super_block *, secno, unsigned);
int hpfs_check_free_dnodes(struct super_block *, int); int hpfs_check_free_dnodes(struct super_block *, int);
void hpfs_free_dnode(struct super_block *, secno); void hpfs_free_dnode(struct super_block *, secno);
struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *, int); struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *);
struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **); struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **);
struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **);
...@@ -222,8 +214,6 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno); ...@@ -222,8 +214,6 @@ void hpfs_remove_fnode(struct super_block *, fnode_secno fno);
/* buffer.c */ /* buffer.c */
void hpfs_lock_creation(struct super_block *);
void hpfs_unlock_creation(struct super_block *);
void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int); void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **); void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int); void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int);
...@@ -247,7 +237,7 @@ void hpfs_del_pos(struct inode *, loff_t *); ...@@ -247,7 +237,7 @@ void hpfs_del_pos(struct inode *, loff_t *);
struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *, struct hpfs_dirent *hpfs_add_de(struct super_block *, struct dnode *,
const unsigned char *, unsigned, secno); const unsigned char *, unsigned, secno);
int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned, int hpfs_add_dirent(struct inode *, const unsigned char *, unsigned,
struct hpfs_dirent *, int); struct hpfs_dirent *);
int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int); int hpfs_remove_dirent(struct inode *, dnode_secno, struct hpfs_dirent *, struct quad_buffer_head *, int);
void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *); void hpfs_count_dnodes(struct super_block *, dnode_secno, int *, int *, int *);
dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno); dnode_secno hpfs_de_as_down_as_possible(struct super_block *, dnode_secno dno);
...@@ -303,7 +293,6 @@ int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned, ...@@ -303,7 +293,6 @@ int hpfs_compare_names(struct super_block *, const unsigned char *, unsigned,
const unsigned char *, unsigned, int); const unsigned char *, unsigned, int);
int hpfs_is_name_long(const unsigned char *, unsigned); int hpfs_is_name_long(const unsigned char *, unsigned);
void hpfs_adjust_length(const unsigned char *, unsigned *); void hpfs_adjust_length(const unsigned char *, unsigned *);
void hpfs_decide_conv(struct inode *, const unsigned char *, unsigned);
/* namei.c */ /* namei.c */
...@@ -346,21 +335,26 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t) ...@@ -346,21 +335,26 @@ static inline time32_t gmt_to_local(struct super_block *s, time_t t)
/* /*
* Locking: * Locking:
* *
* hpfs_lock() is a leftover from the big kernel lock. * hpfs_lock() locks the whole filesystem. It must be taken
* Right now, these functions are empty and only left * on any method called by the VFS.
* for documentation purposes. The file system no longer
* works on SMP systems, so the lock is not needed
* any more.
* *
* If someone is interested in making it work again, this * We don't do any per-file locking anymore, it is hard to
* would be the place to start by adding a per-superblock * review and HPFS is not performance-sensitive anyway.
* mutex and fixing all the bugs and performance issues
* caused by that.
*/ */
static inline void hpfs_lock(struct super_block *s) static inline void hpfs_lock(struct super_block *s)
{ {
struct hpfs_sb_info *sbi = hpfs_sb(s);
mutex_lock(&sbi->hpfs_mutex);
} }
static inline void hpfs_unlock(struct super_block *s) static inline void hpfs_unlock(struct super_block *s)
{ {
struct hpfs_sb_info *sbi = hpfs_sb(s);
mutex_unlock(&sbi->hpfs_mutex);
}
static inline void hpfs_lock_assert(struct super_block *s)
{
struct hpfs_sb_info *sbi = hpfs_sb(s);
WARN_ON(!mutex_is_locked(&sbi->hpfs_mutex));
} }
...@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i) ...@@ -17,7 +17,6 @@ void hpfs_init_inode(struct inode *i)
i->i_uid = hpfs_sb(sb)->sb_uid; i->i_uid = hpfs_sb(sb)->sb_uid;
i->i_gid = hpfs_sb(sb)->sb_gid; i->i_gid = hpfs_sb(sb)->sb_gid;
i->i_mode = hpfs_sb(sb)->sb_mode; i->i_mode = hpfs_sb(sb)->sb_mode;
hpfs_inode->i_conv = hpfs_sb(sb)->sb_conv;
i->i_size = -1; i->i_size = -1;
i->i_blocks = -1; i->i_blocks = -1;
...@@ -116,8 +115,8 @@ void hpfs_read_inode(struct inode *i) ...@@ -116,8 +115,8 @@ void hpfs_read_inode(struct inode *i)
i->i_mode |= S_IFDIR; i->i_mode |= S_IFDIR;
i->i_op = &hpfs_dir_iops; i->i_op = &hpfs_dir_iops;
i->i_fop = &hpfs_dir_ops; i->i_fop = &hpfs_dir_ops;
hpfs_inode->i_parent_dir = fnode->up; hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up);
hpfs_inode->i_dno = fnode->u.external[0].disk_secno; hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno);
if (hpfs_sb(sb)->sb_chk >= 2) { if (hpfs_sb(sb)->sb_chk >= 2) {
struct buffer_head *bh0; struct buffer_head *bh0;
if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0); if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0);
...@@ -133,7 +132,7 @@ void hpfs_read_inode(struct inode *i) ...@@ -133,7 +132,7 @@ void hpfs_read_inode(struct inode *i)
i->i_op = &hpfs_file_iops; i->i_op = &hpfs_file_iops;
i->i_fop = &hpfs_file_ops; i->i_fop = &hpfs_file_ops;
i->i_nlink = 1; i->i_nlink = 1;
i->i_size = fnode->file_size; i->i_size = le32_to_cpu(fnode->file_size);
i->i_blocks = ((i->i_size + 511) >> 9) + 1; i->i_blocks = ((i->i_size + 511) >> 9) + 1;
i->i_data.a_ops = &hpfs_aops; i->i_data.a_ops = &hpfs_aops;
hpfs_i(i)->mmu_private = i->i_size; hpfs_i(i)->mmu_private = i->i_size;
...@@ -144,7 +143,7 @@ void hpfs_read_inode(struct inode *i) ...@@ -144,7 +143,7 @@ void hpfs_read_inode(struct inode *i)
static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode) static void hpfs_write_inode_ea(struct inode *i, struct fnode *fnode)
{ {
struct hpfs_inode_info *hpfs_inode = hpfs_i(i); struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
/*if (fnode->acl_size_l || fnode->acl_size_s) { /*if (le32_to_cpu(fnode->acl_size_l) || le16_to_cpu(fnode->acl_size_s)) {
Some unknown structures like ACL may be in fnode, Some unknown structures like ACL may be in fnode,
we'd better not overwrite them we'd better not overwrite them
hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino); hpfs_error(i->i_sb, "fnode %08x has some unknown HPFS386 stuctures", i->i_ino);
...@@ -187,9 +186,7 @@ void hpfs_write_inode(struct inode *i) ...@@ -187,9 +186,7 @@ void hpfs_write_inode(struct inode *i)
kfree(hpfs_inode->i_rddir_off); kfree(hpfs_inode->i_rddir_off);
hpfs_inode->i_rddir_off = NULL; hpfs_inode->i_rddir_off = NULL;
} }
mutex_lock(&hpfs_inode->i_parent_mutex);
if (!i->i_nlink) { if (!i->i_nlink) {
mutex_unlock(&hpfs_inode->i_parent_mutex);
return; return;
} }
parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir); parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir);
...@@ -200,14 +197,9 @@ void hpfs_write_inode(struct inode *i) ...@@ -200,14 +197,9 @@ void hpfs_write_inode(struct inode *i)
hpfs_read_inode(parent); hpfs_read_inode(parent);
unlock_new_inode(parent); unlock_new_inode(parent);
} }
mutex_lock(&hpfs_inode->i_mutex);
hpfs_write_inode_nolock(i); hpfs_write_inode_nolock(i);
mutex_unlock(&hpfs_inode->i_mutex);
iput(parent); iput(parent);
} else {
mark_inode_dirty(i);
} }
mutex_unlock(&hpfs_inode->i_parent_mutex);
} }
void hpfs_write_inode_nolock(struct inode *i) void hpfs_write_inode_nolock(struct inode *i)
...@@ -226,30 +218,30 @@ void hpfs_write_inode_nolock(struct inode *i) ...@@ -226,30 +218,30 @@ void hpfs_write_inode_nolock(struct inode *i)
} }
} else de = NULL; } else de = NULL;
if (S_ISREG(i->i_mode)) { if (S_ISREG(i->i_mode)) {
fnode->file_size = i->i_size; fnode->file_size = cpu_to_le32(i->i_size);
if (de) de->file_size = i->i_size; if (de) de->file_size = cpu_to_le32(i->i_size);
} else if (S_ISDIR(i->i_mode)) { } else if (S_ISDIR(i->i_mode)) {
fnode->file_size = 0; fnode->file_size = cpu_to_le32(0);
if (de) de->file_size = 0; if (de) de->file_size = cpu_to_le32(0);
} }
hpfs_write_inode_ea(i, fnode); hpfs_write_inode_ea(i, fnode);
if (de) { if (de) {
de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec); de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec));
de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec); de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec));
de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec); de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));
de->read_only = !(i->i_mode & 0222); de->read_only = !(i->i_mode & 0222);
de->ea_size = hpfs_inode->i_ea_size; de->ea_size = cpu_to_le32(hpfs_inode->i_ea_size);
hpfs_mark_4buffers_dirty(&qbh); hpfs_mark_4buffers_dirty(&qbh);
hpfs_brelse4(&qbh); hpfs_brelse4(&qbh);
} }
if (S_ISDIR(i->i_mode)) { if (S_ISDIR(i->i_mode)) {
if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) { if ((de = map_dirent(i, hpfs_inode->i_dno, "\001\001", 2, NULL, &qbh))) {
de->write_date = gmt_to_local(i->i_sb, i->i_mtime.tv_sec); de->write_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_mtime.tv_sec));
de->read_date = gmt_to_local(i->i_sb, i->i_atime.tv_sec); de->read_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_atime.tv_sec));
de->creation_date = gmt_to_local(i->i_sb, i->i_ctime.tv_sec); de->creation_date = cpu_to_le32(gmt_to_local(i->i_sb, i->i_ctime.tv_sec));
de->read_only = !(i->i_mode & 0222); de->read_only = !(i->i_mode & 0222);
de->ea_size = /*hpfs_inode->i_ea_size*/0; de->ea_size = cpu_to_le32(/*hpfs_inode->i_ea_size*/0);
de->file_size = 0; de->file_size = cpu_to_le32(0);
hpfs_mark_4buffers_dirty(&qbh); hpfs_mark_4buffers_dirty(&qbh);
hpfs_brelse4(&qbh); hpfs_brelse4(&qbh);
} else } else
...@@ -269,6 +261,10 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -269,6 +261,10 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
hpfs_lock(inode->i_sb); hpfs_lock(inode->i_sb);
if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root) if (inode->i_ino == hpfs_sb(inode->i_sb)->sb_root)
goto out_unlock; goto out_unlock;
if ((attr->ia_valid & ATTR_UID) && attr->ia_uid >= 0x10000)
goto out_unlock;
if ((attr->ia_valid & ATTR_GID) && attr->ia_gid >= 0x10000)
goto out_unlock;
if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size) if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size > inode->i_size)
goto out_unlock; goto out_unlock;
...@@ -284,7 +280,6 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -284,7 +280,6 @@ int hpfs_setattr(struct dentry *dentry, struct iattr *attr)
} }
setattr_copy(inode, attr); setattr_copy(inode, attr);
mark_inode_dirty(inode);
hpfs_write_inode(inode); hpfs_write_inode(inode);
......
...@@ -21,7 +21,7 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, ...@@ -21,7 +21,7 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id);
return NULL; return NULL;
} }
sec = hpfs_sb(s)->sb_bmp_dir[bmp_block]; sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]);
if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) { 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); hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id);
return NULL; return NULL;
...@@ -46,18 +46,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) ...@@ -46,18 +46,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
struct code_page_data *cpd; struct code_page_data *cpd;
struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0); struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0);
if (!cp) return NULL; if (!cp) return NULL;
if (cp->magic != CP_DIR_MAGIC) { if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) {
printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", cp->magic); printk("HPFS: Code page directory magic doesn't match (magic = %08x)\n", le32_to_cpu(cp->magic));
brelse(bh); brelse(bh);
return NULL; return NULL;
} }
if (!cp->n_code_pages) { if (!le32_to_cpu(cp->n_code_pages)) {
printk("HPFS: n_code_pages == 0\n"); printk("HPFS: n_code_pages == 0\n");
brelse(bh); brelse(bh);
return NULL; return NULL;
} }
cpds = cp->array[0].code_page_data; cpds = le32_to_cpu(cp->array[0].code_page_data);
cpi = cp->array[0].index; cpi = le16_to_cpu(cp->array[0].index);
brelse(bh); brelse(bh);
if (cpi >= 3) { if (cpi >= 3) {
...@@ -66,12 +66,12 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) ...@@ -66,12 +66,12 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
} }
if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL; if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL;
if ((unsigned)cpd->offs[cpi] > 0x178) { if (le16_to_cpu(cpd->offs[cpi]) > 0x178) {
printk("HPFS: Code page index out of sector\n"); printk("HPFS: Code page index out of sector\n");
brelse(bh); brelse(bh);
return NULL; return NULL;
} }
ptr = (unsigned char *)cpd + cpd->offs[cpi] + 6; ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6;
if (!(cp_table = kmalloc(256, GFP_KERNEL))) { if (!(cp_table = kmalloc(256, GFP_KERNEL))) {
printk("HPFS: out of memory for code page table\n"); printk("HPFS: out of memory for code page table\n");
brelse(bh); brelse(bh);
...@@ -125,7 +125,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea ...@@ -125,7 +125,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
if (hpfs_sb(s)->sb_chk) { if (hpfs_sb(s)->sb_chk) {
struct extended_attribute *ea; struct extended_attribute *ea;
struct extended_attribute *ea_end; struct extended_attribute *ea_end;
if (fnode->magic != FNODE_MAGIC) { if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) {
hpfs_error(s, "bad magic on fnode %08lx", hpfs_error(s, "bad magic on fnode %08lx",
(unsigned long)ino); (unsigned long)ino);
goto bail; goto bail;
...@@ -138,7 +138,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea ...@@ -138,7 +138,7 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
(unsigned long)ino); (unsigned long)ino);
goto bail; goto bail;
} }
if (fnode->btree.first_free != if (le16_to_cpu(fnode->btree.first_free) !=
8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { 8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) {
hpfs_error(s, hpfs_error(s,
"bad first_free pointer in fnode %08lx", "bad first_free pointer in fnode %08lx",
...@@ -146,12 +146,12 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea ...@@ -146,12 +146,12 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
goto bail; goto bail;
} }
} }
if (fnode->ea_size_s && ((signed int)fnode->ea_offs < 0xc4 || if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 ||
(signed int)fnode->ea_offs + fnode->acl_size_s + fnode->ea_size_s > 0x200)) { le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) {
hpfs_error(s, hpfs_error(s,
"bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x", "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x",
(unsigned long)ino, (unsigned long)ino,
fnode->ea_offs, fnode->ea_size_s); le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
goto bail; goto bail;
} }
ea = fnode_ea(fnode); ea = fnode_ea(fnode);
...@@ -178,16 +178,20 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff ...@@ -178,16 +178,20 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL; 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 ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD)))
if (hpfs_sb(s)->sb_chk) { if (hpfs_sb(s)->sb_chk) {
if (anode->magic != ANODE_MAGIC || anode->self != ano) { if (le32_to_cpu(anode->magic) != ANODE_MAGIC) {
hpfs_error(s, "bad magic on anode %08x", ano); hpfs_error(s, "bad magic on anode %08x", ano);
goto bail; goto bail;
} }
if (le32_to_cpu(anode->self) != ano) {
hpfs_error(s, "self pointer invalid on anode %08x", ano);
goto bail;
}
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
(anode->btree.internal ? 60 : 40)) { (anode->btree.internal ? 60 : 40)) {
hpfs_error(s, "bad number of nodes in anode %08x", ano); hpfs_error(s, "bad number of nodes in anode %08x", ano);
goto bail; goto bail;
} }
if (anode->btree.first_free != if (le16_to_cpu(anode->btree.first_free) !=
8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { 8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) {
hpfs_error(s, "bad first_free pointer in anode %08x", ano); hpfs_error(s, "bad first_free pointer in anode %08x", ano);
goto bail; goto bail;
...@@ -219,26 +223,26 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno, ...@@ -219,26 +223,26 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
unsigned p, pp = 0; unsigned p, pp = 0;
unsigned char *d = (unsigned char *)dnode; unsigned char *d = (unsigned char *)dnode;
int b = 0; int b = 0;
if (dnode->magic != DNODE_MAGIC) { if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) {
hpfs_error(s, "bad magic on dnode %08x", secno); hpfs_error(s, "bad magic on dnode %08x", secno);
goto bail; goto bail;
} }
if (dnode->self != secno) if (le32_to_cpu(dnode->self) != secno)
hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, dnode->self); hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self));
/* Check dirents - bad dirents would cause infinite /* Check dirents - bad dirents would cause infinite
loops or shooting to memory */ loops or shooting to memory */
if (dnode->first_free > 2048/* || dnode->first_free < 84*/) { if (le32_to_cpu(dnode->first_free) > 2048) {
hpfs_error(s, "dnode %08x has first_free == %08x", secno, dnode->first_free); hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free));
goto bail; goto bail;
} }
for (p = 20; p < dnode->first_free; p += d[p] + (d[p+1] << 8)) { for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) {
struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p);
if (de->length > 292 || (de->length < 32) || (de->length & 3) || p + de->length > 2048) { if (le16_to_cpu(de->length) > 292 || (le16_to_cpu(de->length) < 32) || (le16_to_cpu(de->length) & 3) || p + le16_to_cpu(de->length) > 2048) {
hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
goto bail; goto bail;
} }
if (((31 + de->namelen + de->down*4 + 3) & ~3) != de->length) { if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) {
if (((31 + de->namelen + de->down*4 + 3) & ~3) < de->length && s->s_flags & MS_RDONLY) goto ok; if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(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); hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp);
goto bail; goto bail;
} }
...@@ -251,7 +255,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno, ...@@ -251,7 +255,7 @@ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno,
pp = p; pp = p;
} }
if (p != dnode->first_free) { if (p != le32_to_cpu(dnode->first_free)) {
hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno); hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno);
goto bail; goto bail;
} }
...@@ -277,7 +281,7 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino) ...@@ -277,7 +281,7 @@ dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino)
if (!fnode) if (!fnode)
return 0; return 0;
dno = fnode->u.external[0].disk_secno; dno = le32_to_cpu(fnode->u.external[0].disk_secno);
brelse(bh); brelse(bh);
return dno; return dno;
} }
...@@ -8,39 +8,6 @@ ...@@ -8,39 +8,6 @@
#include "hpfs_fn.h" #include "hpfs_fn.h"
static const char *text_postfix[]={
".ASM", ".BAS", ".BAT", ".C", ".CC", ".CFG", ".CMD", ".CON", ".CPP", ".DEF",
".DOC", ".DPR", ".ERX", ".H", ".HPP", ".HTM", ".HTML", ".JAVA", ".LOG", ".PAS",
".RC", ".TEX", ".TXT", ".Y", ""};
static const char *text_prefix[]={
"AUTOEXEC.", "CHANGES", "COPYING", "CONFIG.", "CREDITS", "FAQ", "FILE_ID.DIZ",
"MAKEFILE", "READ.ME", "README", "TERMCAP", ""};
void hpfs_decide_conv(struct inode *inode, const unsigned char *name, unsigned len)
{
struct hpfs_inode_info *hpfs_inode = hpfs_i(inode);
int i;
if (hpfs_inode->i_conv != CONV_AUTO) return;
for (i = 0; *text_postfix[i]; i++) {
int l = strlen(text_postfix[i]);
if (l <= len)
if (!hpfs_compare_names(inode->i_sb, text_postfix[i], l, name + len - l, l, 0))
goto text;
}
for (i = 0; *text_prefix[i]; i++) {
int l = strlen(text_prefix[i]);
if (l <= len)
if (!hpfs_compare_names(inode->i_sb, text_prefix[i], l, name, l, 0))
goto text;
}
hpfs_inode->i_conv = CONV_BINARY;
return;
text:
hpfs_inode->i_conv = CONV_TEXT;
return;
}
static inline int not_allowed_char(unsigned char c) static inline int not_allowed_char(unsigned char c)
{ {
return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' || return c<' ' || c=='"' || c=='*' || c=='/' || c==':' || c=='<' ||
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment