?? super.c
字號:
} /* Grab the correct time. Technically the spec says this should use the stupid DOS format, but QNX's File System stores a sensible unix date in here, so we use that instead. Maybe make this an option, the fat code in linux has the decoding routines. */ if ((extent->Status & FFS_ENTRY_TIME) == FFS_ENTRY_TIME) i->i_mtime = i->i_atime = i->i_ctime = extent->Time + (extent->Date << 16); /* Add in the size and step to the next entry. For some crazed reason the meanings of primary+sibling swap for entries :< */ if (isflagset(extent->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEEXTENT)) { i->i_size += ((struct ffs2_fileinfo *)extent)->UncompressedExtentLen; // Skip to the next one if (isFNULL(extent->PrimaryPtr) == 0 && (extent->Status & FFS_ENTRY_PRIMARY) != FFS_ENTRY_PRIMARY) cur = extent->PrimaryPtr; else break; } else { i->i_size += sizeof(*extent) + extent->NameLen; // Skip to the next one if (isFNULL(extent->SiblingPtr) == 0 && (extent->Status & FFS_ENTRY_SIBLING) != FFS_ENTRY_SIBLING) cur = extent->SiblingPtr; else break; } } } ffs2_relse(&r);} /*}}}*/// ffs2_mkdir - Make a new directory /*{{{*/// ---------------------------------------------------------------------/* */static int ffs2_mkdir(struct inode *dir, struct dentry *dentry, int mode){ return ffs2_new_entry(dir,dentry,&dentry->d_name,FFS_ENTRY_TYPEDIR);} /*}}}*/// ffs2_create - Create a new file /*{{{*/// ---------------------------------------------------------------------/* */static int ffs2_create(struct inode *dir,struct dentry *dentry,int mode){ return ffs2_new_entry(dir,dentry,&dentry->d_name,FFS_ENTRY_TYPEFILE);} /*}}}*/// ffs2_unlink - Unlink a file /*{{{*/// ---------------------------------------------------------------------/* This does a very unsafe unlink operation. It goes over the linked list of extents and marks them all as erased. If this routine is interrupted the filesystem will have unreclaimable blocks but will still be consistent */static int ffs2_unlink(struct inode *dir,struct dentry *dentry){ struct ffs_read r; struct ffs2_entry *entry; struct ffs2_blockalloc alloc; unsigned long loc; int res; memset(&r,0,sizeof(r)); r.super = dir->i_sb; // Locate the entry in the directory res = ffs2_find_dirent(&r,dir->i_ino,&dentry->d_name,&loc); if (res != 0 || ffs2_find_blockalloc(&r,loc,&alloc) != 0) { ffs2_relse(&r); if (res == -1) return -ENOENT; return -EIO; } entry = (struct ffs2_entry *)r.p; // Dont unlink directories, use rmdir for that if (isflagset(entry->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEDIR)) { ffs2_relse(&r); return -EISDIR; } if (ffs2_erase(&r,loc,0) != 0) { ffs2_relse(&r); return -EIO; } ffs2_relse(&r); return 0;} /*}}}*/// ffs2_rmdir - Remove a directory /*{{{*/// ---------------------------------------------------------------------/* This is similar to ffs2_unlink, except that it checks to make sure the directory is empty before trying to erase */static int ffs2_rmdir(struct inode *dir,struct dentry *dentry){ struct ffs_read r; struct ffs2_entry *entry; unsigned long loc; unsigned long jnk; int res; memset(&r,0,sizeof(r)); r.super = dir->i_sb; // Locate the entry in the directory res = ffs2_find_dirent(&r,dir->i_ino,&dentry->d_name,&loc); if (res != 0 || ffs2_find_blockalloc(&r,loc,0) != 0) { ffs2_relse(&r); if (res == -1) return -ENOENT; return -EIO; } entry = (struct ffs2_entry *)r.p; // Dont unlink a file, use rmdir for that if (!isflagset(entry->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEDIR)) { ffs2_relse(&r); return -ENOTDIR; } // Check for emptyness if (ffs2_find_dirent(&r,loc,0,&jnk) == 0) { ffs2_relse(&r); return -ENOTEMPTY; } if (ffs2_erase(&r,loc,1) != 0) { ffs2_relse(&r); return -EIO; } ffs2_relse(&r); return 0;} /*}}}*/// ffs2_rename - Rename a file /*{{{*/// ---------------------------------------------------------------------/* */static int ffs2_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry){ return -ENOENT;} /*}}}*/// ffs2_file_write - Write a file /*{{{*/// ---------------------------------------------------------------------/* */static ssize_t ffs2_file_write(struct file *filp,const char *buf, size_t count,loff_t *ppos){ struct inode *inode = filp->f_dentry->d_inode; off_t pos; ssize_t written; char *tmp; struct ffs2_entry *entry; struct ffs_read r; unsigned long cur; unsigned long offset; ssize_t res = 0; memset(&r,0,sizeof(r)); r.super = inode->i_sb; // Make sure the inode is sensible if (!inode || !S_ISREG(inode->i_mode)) return -EINVAL; // Get the writing position if (filp->f_flags & O_APPEND) pos = inode->i_size; else pos = *ppos; written = 0; // Get the inode and follow to find the first extent if ((entry = ffs2_find_entry(&r,inode->i_ino)) == 0 || isFNULL(entry->PrimaryPtr) || (entry->Status & FFS_ENTRY_PRIMARY) == FFS_ENTRY_PRIMARY) { cur = inode->i_ino; } else { cur = entry->PrimaryPtr; } // Check for compression (this isnt quite right..) if ((entry->Status >> FFS_ENTRY_COMPIP_SHIFT) != 0xFF) { printk("ffs2: No support for compressed foramt %x\n", entry->Status >> FFS_ENTRY_COMPIP_SHIFT); ffs2_relse(&r); return -EINVAL; } /* Search for the first block that overlaps this block, or the end of the list */ offset = 0; written = 0; tmp = kmalloc(PAGE_SIZE,GFP_KERNEL); while (written < count) { unsigned long oldcur = cur; struct ffs2_fileinfo *extent = (struct ffs2_fileinfo *)ffs2_find_entry(&r,cur); if (extent == 0) break; // This is invoked if there is no extents at all if (cur != inode->i_ino) { if (!isflagset(extent->Status,FFS_ENTRY_TYPEMASK,FFS_ENTRY_TYPEEXTENT)) break; // Skip cur to the next one if (isFNULL(extent->PrimaryPtr) == 0 && (extent->Status & FFS_ENTRY_PRIMARY) != FFS_ENTRY_PRIMARY) cur = extent->PrimaryPtr; else cur = 0xFFFFFFFF; if ((extent->Status & FFS_ENTRY_EXISTS) != FFS_ENTRY_EXISTS) continue; // See if we have entered the copy region if (offset + extent->UncompressedExtentLen > pos) { printk("ffs2: No support for overwriting\n"); res = -EINVAL; break; } } else cur = 0xFFFFFFFF; // Check if the end of this block is the start of the insertion region if (cur == 0xFFFFFFFF && offset + extent->UncompressedExtentLen >= pos) { /* Allocate a new block, write the data and link it to the last block, repeatedly growing the length of the chain */ while (written < count) { unsigned long ext; ssize_t c = count - written; if (c > PAGE_SIZE) c = PAGE_SIZE; if (copy_from_user(tmp,buf,c) != 0) { res = -EFAULT; break; } written += c; if (ffs2_new_extent(&r,tmp,c,&ext) != 0) { res = -EIO; break; } res = update_pointer(&r,oldcur,ext,FFS_PTR_PRIMARY); if (res != 0) break; update_vm_cache(inode,pos,tmp,c); oldcur = ext; pos += c; offset += c; } break; } offset += ((struct ffs2_fileinfo *)extent)->UncompressedExtentLen; if (cur == 0xFFFFFFFF) { printk("ffs2: Sparse files not supported\n"); res = -EINVAL; break; } } kfree(tmp); ffs2_relse(&r); if (res != 0) return res; *ppos = pos; if (pos > inode->i_size) inode->i_size = pos; return written;} /*}}}*/// Kernel Binding /*{{{*/static struct file_operations ffs2_file_operations ={ NULL, /* lseek - default */ generic_file_read, /* read */ ffs2_file_write, /* write */ NULL, /* readdir */ NULL, /* poll - default */ NULL, /* ioctl */ generic_file_mmap, /* mmap */ NULL, /* open */ NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL /* revalidate */};static struct inode_operations ffs2_file_inode_operations ={ &ffs2_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 */ ffs2_readpage, /* readpage */ NULL, /* writepage */ NULL, /* bmap -- not really */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */};static struct file_operations ffs2_dir_operations ={ NULL, /* lseek - default */ NULL, /* read */ NULL, /* write - bad */ ffs2_readdir, /* readdir */ NULL, /* poll - default */ NULL, /* ioctl */ NULL, /* mmap */ NULL, /* open */ NULL, /* flush */ NULL, /* release */ NULL, /* fsync */ NULL, /* fasync */ NULL, /* check_media_change */ NULL /* revalidate */};static struct inode_operations ffs2_dir_inode_operations ={ &ffs2_dir_operations, ffs2_create, /* create */ ffs2_lookup, /* lookup */ NULL, /* link */ ffs2_unlink, /* unlink */ NULL, /* symlink */ ffs2_mkdir, /* mkdir */ ffs2_rmdir, /* rmdir */ NULL, /* mknod */ ffs2_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */};static struct inode_operations ffs2_link_inode_operations ={ NULL, /* no file operations on symlinks */ NULL, /* create */ NULL, /* lookup */ NULL, /* link */ NULL, /* unlink */ NULL, /* symlink */ NULL, /* mkdir */ NULL, /* rmdir */ NULL, /* mknod */ NULL, /* rename */ ffs2_readlink, /* readlink */ ffs2_follow_link, /* follow_link */ NULL, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ NULL, /* truncate */ NULL, /* permission */ NULL, /* smap */};static struct inode_operations *ffs2_inoops[] ={ NULL, /* hardlink, handled elsewhere */ &ffs2_dir_inode_operations, &ffs2_file_inode_operations, &ffs2_link_inode_operations, &blkdev_inode_operations, /* standard handlers */ &chrdev_inode_operations, NULL, /* socket */ NULL, /* fifo */};static struct super_operations ffs2_ops ={ ffs2_read_inode, /* read inode */ NULL, /* write inode */ NULL, /* put inode */ NULL, /* delete inode */ NULL, /* notify change */ ffs2_put_super, /* put super */ NULL, /* write super */ ffs2_statfs, /* statfs */ NULL /* remount */};static struct file_system_type ffs2_fs_type ={ "ffs2", FS_REQUIRES_DEV, ffs2_read_super, NULL}; /*}}}*/// Init Stuff /*{{{*/int __init init_ffs2_fs(){ return register_filesystem(&ffs2_fs_type);}#ifdef MODULEEXPORT_NO_SYMBOLS;int init_module(void){ return init_ffs2_fs();}void cleanup_module(){ unregister_filesystem(&ffs2_fs_type);}#endif /*}}}*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -