From: Adrian M. <zx8...@us...> - 2003-05-13 22:29:30
|
Update of /cvsroot/linuxdc/linux-sh-dc/fs/vmufs In directory sc8-pr-cvs1:/tmp/cvs-serv22192/fs/vmufs Modified Files: Tag: linux-sh-dc-2_4-branch vmufs.h inode.c super.c Log Message: Updated vmufs with more write support: BEWARE - experimental code Index: vmufs.h =================================================================== RCS file: /cvsroot/linuxdc/linux-sh-dc/fs/vmufs/Attic/vmufs.h,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -d -r1.1.2.4 -r1.1.2.5 --- vmufs.h 3 May 2003 16:31:14 -0000 1.1.2.4 +++ vmufs.h 13 May 2003 22:29:26 -0000 1.1.2.5 @@ -8,6 +8,8 @@ #define VMUFS_NAMELEN 12 +#define VMUFS_ZEROBLOCK 32768 + extern struct inode_operations vmufs_inode_operations; extern struct inode_operations vmufs_file_inode_operations; Index: inode.c =================================================================== RCS file: /cvsroot/linuxdc/linux-sh-dc/fs/vmufs/Attic/inode.c,v retrieving revision 1.1.2.16 retrieving revision 1.1.2.17 diff -u -d -r1.1.2.16 -r1.1.2.17 --- inode.c 3 May 2003 16:31:14 -0000 1.1.2.16 +++ inode.c 13 May 2003 22:29:26 -0000 1.1.2.17 @@ -62,6 +62,7 @@ bh->b_data + 4 + (fno % 0x10) * 0x20, 12); + fno++; if ((fno / 0x10) > (vmudetails->dir_bnum - blck_read)) { brelse(bh); @@ -84,7 +85,12 @@ /* No files at all */ return ERR_PTR(error); } - if (memcmp(dent->d_name.name, first_one->fname, 12) != 0) { + int filenamelen = strlen(dent->d_name.name); + if (filenamelen > 12) + filenamelen = 12; + if (memcmp + (dent->d_name.name, first_one->fname, + filenamelen) != 0) { if (first_one->next) { first_one = first_one->next; kfree(first_one->prev); @@ -138,7 +144,7 @@ { /* Create an inode */ if (de->d_name.len > VMUFS_NAMELEN) - return (ERR_PTR(-ENAMETOOLONG)); + return -ENAMETOOLONG; int y; struct inode *inode; @@ -157,7 +163,7 @@ /* Is this an executible file? */ if (imode & 73) { /*Octal 111 */ - inode->i_ino = 0; + inode->i_ino = VMUFS_ZEROBLOCK; /* But this already allocated? */ bh_fat = bread(sb->s_dev, vmudetails->fat_bnum, @@ -173,7 +179,7 @@ } else { /*Look for a free block in the FAT */ - long nextblock = 199; /*TO DO: Make this portable */ + long nextblock = vmudetails->numblocks - 1; bh_fat = bread(sb->s_dev, vmudetails->fat_bnum, sb->s_blocksize); @@ -226,14 +232,22 @@ /* Have the directory entry * so now update it */ int z = (y % 0x10) * 0x20; - if (inode->i_ino != 0) + if (inode->i_ino != VMUFS_ZEROBLOCK) bh->b_data[z] = 0x33; /* data file */ else bh->b_data[z] = 0xcc; if ((bh->b_data[z + 1] != (char) 0x00) && (bh->b_data[z + 1] != (char) 0xff)) bh->b_data[z + 1] = (char) 0x00; - ((__u16 *) bh->b_data)[z / 2 + 1] = cpu_to_le16(inode->i_ino); + if (inode->i_ino != VMUFS_ZEROBLOCK) { + ((__u16 *) bh->b_data)[z / 2 + 1] = + cpu_to_le16(inode->i_ino); + ((__u16 *) bh->b_data)[z / 2 + 0x0D] = 0; + } else { + ((__u16 *) bh->b_data)[z / 2 + 1] = 0; + ((__u16 *) bh->b_data)[z / 2 + 0x0D] = 1; + } + /* Name */ memset((char *) (bh->b_data + z + 0x04), '\0', 0x0C); memcpy((char *) (bh->b_data + z + 0x04), ((de->d_name).name), @@ -274,10 +288,6 @@ ((__u16 *) bh->b_data)[z / 2 + 0x0C] = cpu_to_le16(inode->i_blocks); - if (inode->i_ino != 0) - ((__u16 *) bh->b_data)[z / 2 + 0x0D] = 0; - else - ((__u16 *) bh->b_data)[z / 2 + 0x0D] = 1; /*game */ inode->i_mtime = unix_date; mark_buffer_dirty(bh); brelse(bh); @@ -309,6 +319,7 @@ int vmufs_readdir(struct file *filp, void *dirent, filldir_t filldir) { + int filenamelen; struct dentry *dentry = filp->f_dentry; struct inode *inode = dentry->d_inode; struct super_block *sb = inode->i_sb; @@ -353,8 +364,7 @@ bh = bread(sb->s_dev, blck_read, 512); } - saved_file->ftype = - ((__u8 *) bh->b_data)[0 + ((i - 2) % 0x10) * 0x20]; + saved_file->ftype = bh->b_data[((i - 2) % 0x10) * 0x20]; if (saved_file->ftype == 0) break; @@ -364,12 +374,16 @@ ((i - 2) % 0x10) * 0x10]); + if (saved_file->fblk == 0) + saved_file->fblk = VMUFS_ZEROBLOCK; /*Make sure we can see file */ memcpy(saved_file->fname, bh->b_data + 4 + ((i - 2) % 0x10) * 0x20, 12); - + filenamelen = strlen(saved_file->fname); + if (filenamelen > 12) + filenamelen = 12; if (filldir - (dirent, saved_file->fname, 12, i++, saved_file->fblk, - DT_REG) < 0) { + (dirent, saved_file->fname, filenamelen, i++, + saved_file->fblk, DT_REG) < 0) { goto finish; } @@ -393,10 +407,61 @@ int vmufs_game_write(struct file *file, const char *buf, char *writebuf, - size_t count) + size_t count, loff_t * ppos) { - /* Assume this is a game */ - return -EIO; + __u16 fatdata; + struct buffer_head *bh_fat, *bh; + struct inode *in = (file->f_dentry)->d_inode; + struct super_block *sb = in->i_sb; + struct memcard *vmudetails = + ((struct memcard *) sb->u.generic_sbp); + + unsigned long blkoffset = *ppos >> in->i_sb->s_blocksize_bits; + if (blkoffset < 1) { + /* Additional sanity check */ + kfree(writebuf); + return -EIO; + } + unsigned long blksize = in->i_blksize; + + /* Is the next block free in the VMU? */ + bh_fat = bread(in->i_sb->s_dev, vmudetails->fat_bnum, blksize); + fatdata = ((__u16 *) bh_fat->b_data)[(__u16) blkoffset]; + + if (fatdata != 0xfffc) { + printk(KERN_ERR + "vmufs: Cannot save game file - insufficient linear space\n"); + kfree(writebuf); + return -EFBIG; + } + + /*Now we have the space - write the block out */ + bh = bread(sb->s_dev, blkoffset, in->i_blksize); + if (count < in->i_blksize) + memset((char *) (bh->b_data), '\0', in->i_blksize); + memcpy((char *) (bh->b_data), writebuf, count); + mark_buffer_dirty(bh); + brelse(bh); + in->i_size += in->i_blksize; + in->i_blocks++; + /*Now update the FAT */ + + + ((__u16 *) (bh_fat->b_data))[(__u16) blkoffset] = 0xfffa; + ((__u16 *) (bh_fat->b_data))[((__u16) (blkoffset - 1))] = + cpu_to_le16(blkoffset); + mark_buffer_dirty(bh_fat); + + + brelse(bh_fat); + + + kfree(writebuf); + *ppos += count; + return count; + + + } ssize_t vmufs_file_write(struct file * file, const char *buf, size_t count, @@ -429,65 +494,62 @@ copy_from_user(writebuf, buf, count); - if (in->i_ino == 0) { - vmufs_game_write(file, buf, writebuf, count); - } else { - /* We have a data file - - * so let's write it out to - * the vmu */ + /* Handle game files */ + unsigned long inode_num = in->i_ino; + if (inode_num == VMUFS_ZEROBLOCK) + inode_num = 0; - /*Start by writing out to first block */ - if (blkoffset == 0) { - unsigned long currentblock = in->i_ino; - __u16 fatdata; - bh = bread(sb->s_dev, in->i_ino, in->i_blksize); - if (count < in->i_blksize) - memset((char *) (bh->b_data), '\0', - in->i_blksize); - memcpy((char *) (bh->b_data), writebuf, count); - mark_buffer_dirty(bh); - brelse(bh); - in->i_size = in->i_blksize; /* will increment as we grow */ - in->i_blocks = 1; - /* Update FAT */ - bh_fat = - bread(in->i_sb->s_dev, vmudetails->fat_bnum, - blksize); - /*Wipe out any old FAT records for this inode */ - do { - fatdata = - ((__u16 *) bh_fat-> - b_data)[(__u16) currentblock]; - if (fatdata == 0xfffc) - break; /* already empty */ - ((__u16 *) (bh_fat-> - b_data))[(__u16) currentblock] - = 0xfffc; - mark_buffer_dirty(bh_fat); - if (fatdata == 0xfffa) - break; /* end of file */ - } while (1); - /* Avoid writes to mtd if possible - * so check if a write is really - * required here */ + /*Start by writing out to first block */ + if (blkoffset == 0) { + unsigned long currentblock = inode_num; + __u16 fatdata; + bh = bread(sb->s_dev, inode_num, in->i_blksize); + if (count < in->i_blksize) + memset((char *) (bh->b_data), '\0', in->i_blksize); + memcpy((char *) (bh->b_data), writebuf, count); + mark_buffer_dirty(bh); + brelse(bh); + in->i_size = in->i_blksize; /* will increment as we grow */ + in->i_blocks = 1; + /* Update FAT */ + bh_fat = + bread(in->i_sb->s_dev, vmudetails->fat_bnum, blksize); + /*Wipe out any old FAT records for this inode */ + do { fatdata = ((__u16 *) bh_fat-> - b_data)[(__u16) (in->i_ino)]; - if (fatdata != 0xfffa) { - ((__u16 *) (bh_fat->b_data))[(__u16) (in-> - i_ino)] - = 0xfffa; - mark_buffer_dirty(bh_fat); - } - brelse(bh_fat); - + b_data)[(__u16) currentblock]; + if (fatdata == 0xfffc) + break; /* already empty */ + ((__u16 *) (bh_fat->b_data))[(__u16) currentblock] + = 0xfffc; + mark_buffer_dirty(bh_fat); + if (fatdata == 0xfffa) + break; /* end of file */ + } while (1); + /* Avoid writes to mtd if possible + * so check if a write is really + * required here */ + fatdata = ((__u16 *) bh_fat->b_data)[(__u16) (inode_num)]; + if (fatdata != 0xfffa) { + ((__u16 *) (bh_fat->b_data))[(__u16) (inode_num)] + = 0xfffa; + mark_buffer_dirty(bh_fat); } - /* Now every other block */ - else { + brelse(bh_fat); + + } + /* Now every other block */ + else { + if (inode_num == 0) { + return vmufs_game_write(file, buf, writebuf, count, + ppos); + } else { + /*Look for a free block in the FAT */ __u16 fatdata; - unsigned long nextblock = in->i_ino - 1; + unsigned long nextblock = inode_num - 1; bh_fat = bread(in->i_sb->s_dev, vmudetails->fat_bnum, blksize); @@ -525,7 +587,7 @@ 0xfffa; mark_buffer_dirty(bh_fat); } - int previousblock = in->i_ino; + int previousblock = inode_num; do { fatdata = ((__u16 *) bh_fat-> @@ -534,7 +596,7 @@ || (fatdata == 0xfffa)) { ((__u16 *) bh_fat-> b_data)[previousblock] = - nextblock; + cpu_to_le16(nextblock); mark_buffer_dirty(bh_fat); break; } @@ -563,6 +625,9 @@ loff_t * ppos) { struct inode *in = file->f_dentry->d_inode; + unsigned long inode_num = in->i_ino; + if (inode_num == VMUFS_ZEROBLOCK) + inode_num = 0; unsigned long blkoffset = *ppos >> in->i_sb->s_blocksize_bits; unsigned long blksize = in->i_blksize; unsigned long blcks_to_read, x; @@ -586,7 +651,7 @@ readbuf = kmalloc(count, GFP_KERNEL); /* Traverse through FAT to read the blocks in */ x = 0; - next_block = in->i_ino; + next_block = inode_num; bh_fat = bread(in->i_sb->s_dev, vmudetails->fat_bnum, blksize); /*Walk through to where we are */ if (blkoffset > 0) { Index: super.c =================================================================== RCS file: /cvsroot/linuxdc/linux-sh-dc/fs/vmufs/Attic/super.c,v retrieving revision 1.1.2.15 retrieving revision 1.1.2.16 diff -u -d -r1.1.2.15 -r1.1.2.16 --- super.c 3 May 2003 16:31:14 -0000 1.1.2.15 +++ super.c 13 May 2003 22:29:26 -0000 1.1.2.16 @@ -94,15 +94,22 @@ in->i_version = ++event; brelse(bh); } else { - int blck_read = vmudetails->dir_bnum; - struct buffer_head *bh = bread(sb->s_dev, blck_read, 512); - int y; - if (in->i_ino > (vmudetails->dir_len * 0x10)) { + if ((in->i_ino > vmudetails->numblocks) + && (in->i_ino != VMUFS_ZEROBLOCK)) { /* Not here */ - brelse(bh); + printk(KERN_INFO + "vmufs: Attempt to access file which cannot exist on this size of VMU\n"); return; } + unsigned long inode_num = in->i_ino; + if (inode_num == VMUFS_ZEROBLOCK) + inode_num = 0; + + int blck_read = vmudetails->dir_bnum; + struct buffer_head *bh = bread(sb->s_dev, blck_read, 512); + int y; + /* * Do the same here.. clear out the old mask, and force @@ -114,7 +121,7 @@ in->i_mode |= S_IFREG; /* Scan through the directory to find the matching file */ - for (y = 0; y < (vmudetails->dir_len * 0x10); y++) { + for (y = 0; y < vmudetails->numblocks; y++) { if ((y / 0x10) > (vmudetails->dir_bnum - blck_read)) { brelse(bh); @@ -123,12 +130,14 @@ } if (le16_to_cpu (((__u16 *) bh->b_data)[(y % 0x10) * 0x10 + - 0x01]) == in->i_ino) + 0x01]) == inode_num) break; } - if (y >= (vmudetails->dir_len * 0x10)) { + if (y >= vmudetails->numblocks) { brelse(bh); + printk(KERN_INFO + "vmufs: could not find this file on the vmu\n"); /* TO DO: error return required */ return; } @@ -176,7 +185,7 @@ 0x0C]); in->i_size = in->i_blocks * 512; in->i_blksize = 512; - + /*printk(KERN_INFO "File has inode %i and is %i bytes long\n", in->i_ino, in->i_size); */ brelse(bh); } } @@ -215,7 +224,8 @@ int z, y, x, blck_read; __u16 nextblock, fatdata; - + if (in->i_ino == VMUFS_ZEROBLOCK) + in->i_ino = 0; sb = in->i_sb; vmudetails = (struct memcard *) sb->u.generic_sbp; bh = bread(sb->s_dev, vmudetails->fat_bnum, in->i_blksize); @@ -298,21 +308,22 @@ { struct buffer_head *bh; + unsigned long inode_num; int y, blck_read, name_len; struct super_block *sb = in->i_sb; struct memcard *vmudetails = ((struct memcard *) sb->u.generic_sbp); - - printk(KERN_INFO "In vmufs_write_inode\n"); - + if (in->i_ino == VMUFS_ZEROBLOCK) + inode_num = 0; + else + inode_num = in->i_ino; /* update the directory and inode details */ - /* Now search for the directory entry */ blck_read = vmudetails->dir_bnum; bh = bread(sb->s_dev, blck_read, in->i_blksize); - for (y = 0; y < (vmudetails->dir_len * 0x10); y++) { + for (y = 0; y < vmudetails->numblocks; y++) { if ((y / 0x10) > (vmudetails->dir_bnum - blck_read)) { brelse(bh); blck_read--; @@ -320,20 +331,20 @@ } if (le16_to_cpu (((__u16 *) bh->b_data)[(y % 0x10) * 0x10 + - 0x01]) == in->i_ino) + 0x01]) == inode_num) break; } /* Have the directory entry * so now update it */ int z = (y % 0x10) * 0x20; - if (in->i_ino != 0) + if (inode_num != 0) bh->b_data[z] = 0x33; /* data file */ else bh->b_data[z] = 0xcc; if ((bh->b_data[z + 1] != (char) 0x00) && (bh->b_data[z + 1] != (char) 0xff)) bh->b_data[z + 1] = (char) 0x00; - ((__u16 *) bh->b_data)[z / 2 + 1] = cpu_to_le16(in->i_ino); + ((__u16 *) bh->b_data)[z / 2 + 1] = cpu_to_le16(inode_num); /* BCD timestamp it */ unsigned long unix_date = CURRENT_TIME; int year, day, nl_day, month; /*inspired by FAT driver */ @@ -369,10 +380,10 @@ bh->b_data[z + 0x16] = bcd_from_u8((__u8) (unix_date % 60)); ((__u16 *) bh->b_data)[z / 2 + 0x0C] = cpu_to_le16(in->i_blocks); - if (in->i_ino != 0) + if (inode_num != 0) ((__u16 *) bh->b_data)[z / 2 + 0x0D] = 0; else - ((__u16 *) bh->b_data)[z / 2 + 0x0D] = 1; /*game */ + ((__u16 *) bh->b_data)[z / 2 + 0x0D] = cpu_to_le16(1); /*game */ in->i_mtime = unix_date; mark_buffer_dirty(bh); brelse(bh); @@ -402,6 +413,14 @@ } + +/********************** + * vmufs_read_super * + * Read directory * + * locations off * + * superblock * + * ********************/ + static struct super_block *vmufs_read_super(struct super_block *sb, void *data, int silent) { @@ -426,20 +445,13 @@ struct memcard *vmudata = kmalloc(sizeof(struct memcard), GFP_KERNEL); - vmudata->numblocks = z; + + vmudata->numblocks = le16_to_cpu(((__u16 *) bh->b_data)[0x50 / 2]); /*User blocks */ vmudata->sb_bnum = z - 1; - vmudata->fat_bnum = z - 2; - if (z < 512) - vmudata->fat_len = 1; - else if (z == 512) - vmudata->fat_len = 2; - else - vmudata->fat_len = 4; - vmudata->dir_bnum = vmudata->fat_bnum - vmudata->fat_len; - if (z == 128) - vmudata->dir_len = 7; - else - vmudata->dir_len = 13 * (z / 256); + vmudata->fat_bnum = le16_to_cpu(((__u16 *) bh->b_data)[0x46 / 2]); + vmudata->fat_len = le16_to_cpu(((__u16 *) bh->b_data)[0x48 / 2]); + vmudata->dir_bnum = le16_to_cpu(((__u16 *) bh->b_data)[0x4a / 2]); + vmudata->dir_len = le16_to_cpu(((__u16 *) bh->b_data)[0x4c / 2]); sb->u.generic_sbp = vmudata; struct inode *root_i; |