?? file.c
字號(hào):
/* * linux/fs/affs/file.c * * (c) 1996 Hans-Joachim Widmaier - Rewritten * * (C) 1993 Ray Burr - Modified for Amiga FFS filesystem. * * (C) 1992 Eric Youngdale Modified for ISO9660 filesystem. * * (C) 1991 Linus Torvalds - minix filesystem * * affs regular file handling primitives */#include <asm/segment.h>#include <asm/system.h>#include <linux/sched.h>#include <linux/affs_fs.h>#include <linux/fcntl.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/locks.h>#include <linux/dirent.h>#include <linux/fs.h>#include <linux/amigaffs.h>#include <linux/mm.h>#include <linux/pagemap.h>#define MIN(a,b) (((a)<(b))?(a):(b))#define MAX(a,b) (((a)>(b))?(a):(b))static int affs_file_read_ofs(struct inode *inode, struct file *filp, char *buf, int count);static int affs_file_write(struct inode *inode, struct file *filp, const char *buf, int count);static int affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, int count);static void affs_release_file(struct inode *inode, struct file *filp);static struct file_operations affs_file_operations = { NULL, /* lseek - default */ generic_file_read, /* read */ affs_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ generic_file_mmap, /* mmap */ NULL, /* no special open is needed */ affs_release_file, /* release */ file_fsync /* brute force, but works */};struct inode_operations affs_file_inode_operations = { &affs_file_operations, /* default file operations */ NULL, /* create */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ generic_readpage, /* readpage */ NULL, /* writepage */ affs_bmap, /* bmap */ affs_truncate, /* truncate */ NULL, /* permission */ NULL /* smap */};static struct file_operations affs_file_operations_ofs = { NULL, /* lseek - default */ affs_file_read_ofs, /* read */ affs_file_write_ofs, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ NULL, /* ioctl - default */ NULL, /* mmap */ NULL, /* no special open is needed */ affs_release_file, /* release */ file_fsync /* brute force, but works */};struct inode_operations affs_file_inode_operations_ofs = { &affs_file_operations_ofs, /* default file operations */ NULL, /* create */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ affs_truncate, /* truncate */ NULL, /* permission */ NULL /* smap */};intaffs_bmap(struct inode *inode, int block){ struct buffer_head *bh; int ext, key; int ptype, stype; pr_debug("AFFS: bmap(%lu,%d)\n",inode->i_ino,block); if (block < 0) { printk("affs_bmap: block < 0\n"); return 0; } /* If this is a hard link, quietly exchange the inode with the original */ key = inode->u.affs_i.i_original ? inode->u.affs_i.i_original : inode->i_ino; ext = block / AFFS_I2HSIZE(inode); if (ext) { if (ext > inode->u.affs_i.i_max_ext) ext = inode->u.affs_i.i_max_ext; if (ext) key = inode->u.affs_i.i_ext[ext - 1]; block -= ext * AFFS_I2HSIZE(inode); } for (;;) { bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!bh) return 0; if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || (ptype != T_SHORT && ptype != T_LIST) || stype != ST_FILE) { affs_brelse(bh); return 0; } if (block < AFFS_I2HSIZE(inode)) break; block -= AFFS_I2HSIZE(inode); key = htonl(FILE_END(bh->b_data,inode)->extension); affs_brelse(bh); if (ext < EXT_CACHE_SIZE - 1) { inode->u.affs_i.i_ext[ext] = key; inode->u.affs_i.i_max_ext = ++ext; } } key = AFFS_GET_HASHENTRY(bh->b_data,(AFFS_I2HSIZE(inode) - 1) - block); affs_brelse(bh); return key;}struct buffer_head *affs_getblock(struct inode *inode, int block){ struct buffer_head *bh; struct buffer_head *ebh; int key; int ext; int cnt, j, pt; pr_debug("AFFS: getblock(%lu,%d)\n",inode->i_ino,block); if (block < 0) return NULL; key = inode->i_ino; pt = T_SHORT; ext = block / AFFS_I2HSIZE(inode); if (ext) { if (ext > inode->u.affs_i.i_max_ext) ext = inode->u.affs_i.i_max_ext; if (ext) { key = inode->u.affs_i.i_ext[ext - 1]; block -= ext * AFFS_I2HSIZE(inode); pt = T_LIST; } } for (;;) { bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!bh) return NULL; if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cnt,&j) || cnt != pt || j != ST_FILE) { printk("AFFS: getblock(): inode %d is not a valid %s\n",key, pt == T_SHORT ? "file header" : "extension block"); affs_brelse(bh); return NULL; } j = htonl(((struct file_front *)bh->b_data)->block_count); while (j < AFFS_I2HSIZE(inode) && j <= block) { key = affs_new_data(inode); if (!key) break; lock_super(inode->i_sb); if (AFFS_BLOCK(bh->b_data,inode,j)) { unlock_super(inode->i_sb); printk("AFFS: getblock(): block already allocated\n"); affs_free_block(inode->i_sb,key); j++; continue; } unlock_super(inode->i_sb); AFFS_BLOCK(bh->b_data,inode,j) = ntohl(key); j++; } if (pt == T_SHORT) ((struct file_front *)bh->b_data)->first_data = AFFS_BLOCK(bh->b_data,inode,0); ((struct file_front *)bh->b_data)->block_count = ntohl(j); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); mark_buffer_dirty(bh,1); if (block < j) break; if (j < AFFS_I2HSIZE(inode)) { affs_brelse(bh); return NULL; } block -= AFFS_I2HSIZE(inode); key = htonl(FILE_END(bh->b_data,inode)->extension); if (!key) { key = affs_new_header(inode); if (!key) { affs_brelse(bh); return NULL; } ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!ebh) { affs_free_block(inode->i_sb,key); return NULL; } ((struct file_front *)ebh->b_data)->primary_type = ntohl(T_LIST); ((struct file_front *)ebh->b_data)->own_key = ntohl(key); FILE_END(ebh->b_data,inode)->secondary_type = ntohl(ST_FILE); FILE_END(ebh->b_data,inode)->parent = ntohl(inode->i_ino); affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5); FILE_END(bh->b_data,inode)->extension = ntohl(key); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); bh = ebh; } affs_brelse(bh); pt = T_LIST; if (ext < EXT_CACHE_SIZE - 1) { inode->u.affs_i.i_ext[ext] = key; inode->u.affs_i.i_max_ext = ++ext; } } key = htonl(AFFS_BLOCK(bh->b_data,inode,block)); affs_brelse(bh); if (!key) return NULL; return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));}struct buffer_head *affs_getblock_ofs(struct inode *inode, int block, int *blk_key){ struct buffer_head *bh; struct buffer_head *pbh; struct buffer_head *ebh; int key; int ext; int cnt, j, pt; pr_debug("AFFS: getblock_ofs(%lu,%d)\n",inode->i_ino,block); if (block < 0) return NULL; key = inode->i_ino; pt = T_SHORT; ext = block / AFFS_I2HSIZE(inode); if (ext) { if (ext > inode->u.affs_i.i_max_ext) ext = inode->u.affs_i.i_max_ext; if (ext) { key = inode->u.affs_i.i_ext[ext - 1]; block -= ext * AFFS_I2HSIZE(inode); pt = T_LIST; } } pbh = NULL; for (;;) { bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!bh) return NULL; if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cnt,&j) || cnt != pt || j != ST_FILE) { printk("AFFS: getblock(): inode %d is not a valid %s\n",key, pt == T_SHORT ? "file header" : "extension block"); affs_brelse(bh); return NULL; } j = htonl(((struct file_front *)bh->b_data)->block_count); while (j < AFFS_I2HSIZE(inode) && j <= block) { if (!pbh && inode->u.affs_i.i_lastblock >= 0) { if (j > 0) pbh = affs_bread(inode->i_dev,ntohl(AFFS_BLOCK(bh->b_data,inode,j - 1)), AFFS_I2BSIZE(inode)); else pbh = affs_getblock_ofs(inode,inode->u.affs_i.i_lastblock,&key); if (!pbh) { printk("AFFS: getblock(): cannot get last block in file\n"); break; } } key = affs_new_data(inode); if (!key) break; lock_super(inode->i_sb); if (AFFS_BLOCK(bh->b_data,inode,j)) { unlock_super(inode->i_sb); printk("AFFS: getblock(): block already allocated\n"); affs_free_block(inode->i_sb,key); j++; continue; } AFFS_BLOCK(bh->b_data,inode,j) = ntohl(key); unlock_super(inode->i_sb); ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!ebh) { printk("AFFS: getblock(): cannot get block %d\n",key); affs_free_block(inode->i_sb,key); AFFS_BLOCK(bh->b_data,inode,j) = 0; break; } inode->u.affs_i.i_lastblock++; DATA_FRONT(ebh)->primary_type = ntohl(T_DATA); DATA_FRONT(ebh)->header_key = ntohl(inode->i_ino); DATA_FRONT(ebh)->sequence_number = ntohl(inode->u.affs_i.i_lastblock + 1); if (pbh) { DATA_FRONT(pbh)->data_size = ntohl(AFFS_I2BSIZE(inode) - 24); DATA_FRONT(pbh)->next_data = ntohl(key); affs_fix_checksum(AFFS_I2BSIZE(inode),pbh->b_data,5); mark_buffer_dirty(pbh,0); mark_buffer_dirty(ebh,0); affs_brelse(pbh); } pbh = ebh; j++; } if (pt == T_SHORT) ((struct file_front *)bh->b_data)->first_data = AFFS_BLOCK(bh->b_data,inode,0); ((struct file_front *)bh->b_data)->block_count = ntohl(j); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); mark_buffer_dirty(bh,1); if (block < j) { if (pbh) affs_brelse(pbh); break; } if (j < AFFS_I2HSIZE(inode)) { affs_brelse(bh); return NULL; } block -= AFFS_I2HSIZE(inode); key = htonl(FILE_END(bh->b_data,inode)->extension); if (!key) { key = affs_new_header(inode); if (!key) { affs_brelse(bh); return NULL; } ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!ebh) { affs_free_block(inode->i_sb,key); return NULL; } ((struct file_front *)ebh->b_data)->primary_type = ntohl(T_LIST); ((struct file_front *)ebh->b_data)->own_key = ntohl(key); FILE_END(ebh->b_data,inode)->secondary_type = ntohl(ST_FILE); FILE_END(ebh->b_data,inode)->parent = ntohl(inode->i_ino); affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5); FILE_END(bh->b_data,inode)->extension = ntohl(key); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); bh = ebh; }
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -