/* * Lookup the data. This is trivial - if the dentry didn't already * exist, we know it is negative. */ static struct dentry * ptpfs_root_lookup(struct inode *dir, struct dentry *dentry) { // printk(KERN_INFO "%s\n", __FUNCTION__); struct ptp_storage_ids storageids; int x; char fsname[256]; int typeCount[5]; memset(&storageids,0,sizeof(storageids)); //add by evan memset(typeCount,0,sizeof(typeCount)); if (ptp_getstorageids(PTPFSSB(dir->i_sb), &storageids)!=PTP_RC_OK) { printk(KERN_INFO "Error getting storage ids\n"); storageids.n = 0; storageids.storage = NULL; } int offset = 0; for (x = 0; x < storageids.n; x++) { struct ptp_storage_info storageinfo; if ((storageids.storage[x]&0x0000ffff)==0) continue; memset(&storageinfo,0,sizeof(storageinfo)); if (ptp_getstorageinfo(PTPFSSB(dir->i_sb), storageids.storage[x],&storageinfo)!=PTP_RC_OK) { printk(KERN_INFO "Error getting storage info\n"); } else { get_root_dir_name(&storageinfo,fsname,typeCount); offset++; if (!memcmp(fsname,dentry->d_name.name,dentry->d_name.len)) { struct inode *newi = ptpfs_get_inode(dir->i_sb, S_IFDIR | S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH , 0,storageids.storage[x]); PTPFSINO(newi)->parent = dir; //dir should be root directory //newi->i_fop = &ptpfs_stgdir_operations; //newi->i_op = &ptpfs_stgdir_inode_operations; PTPFSINO(newi)->type = INO_TYPE_STGDIR; PTPFSINO(newi)->storage = storageids.storage[x]; if (newi) d_add(dentry, newi); ptp_free_storage_ids(&storageids); ptp_free_storage_info(&storageinfo); return NULL; } ptp_free_storage_info(&storageinfo); } } ptp_free_storage_ids(&storageids); return NULL; }
static int ptpfs_release(struct inode *ino, struct file *filp) { //printk(KERN_INFO "%s object:%X dcount: %d\n", __FUNCTION__,ino->i_ino, filp->f_dentry->d_count); struct ptp_data_buffer *data=(struct ptp_data_buffer*)filp->private_data; if (data) { switch (filp->f_flags & O_ACCMODE) { case O_RDWR: case O_WRONLY: { struct ptp_object_info object; memset(&object,0,sizeof(object)); if (ptp_getobjectinfo(PTPFSSB(ino->i_sb),ino->i_ino,&object)!=PTP_RC_OK) { ptp_free_data_buffer(data); kfree(data); return -EPERM; } ptp_deleteobject(PTPFSSB(ino->i_sb),ino->i_ino,0); int count = 0; int x; for (x = 0; x < data->num_blocks; x++) { count += data->blocks[x].block_size; } int storage = object.storage_id; int parent = object.parent_object; int handle = ino->i_ino; object.object_compressed_size=count; int ret = ptp_sendobjectinfo(PTPFSSB(ino->i_sb), &storage, &parent, &handle, &object); ret = ptp_sendobject(PTPFSSB(ino->i_sb),data,count); ino->i_size = count; ino->i_mtime = CURRENT_TIME; ptpfs_free_inode_data(ino);//uncache ptpfs_free_inode_data(PTPFSINO(ino) -> parent);//uncache //the inode number will change. Kill this inode so next dir lookup will create a new one dput(filp->f_dentry); //iput(ino); } break; } ptp_free_data_buffer(data); kfree(data); } return 0; }
int ptpfs_unlink(struct inode *dir,struct dentry *d) { //printk(KERN_INFO "%s %s\n",__FUNCTION__,d->d_name.name); int x; struct ptpfs_inode_data* ptpfs_data = PTPFSINO(dir); if (!ptpfs_get_dir_data(dir)) { return -EPERM; } if (ptpfs_data->type != INO_TYPE_DIR && ptpfs_data->type != INO_TYPE_STGDIR) { return -EPERM; } for (x = 0; x < ptpfs_data->data.dircache.num_files; x++) { if (!memcmp(ptpfs_data->data.dircache.file_info[x].filename,d->d_name.name,d->d_name.len)) { int ret = ptp_deleteobject(PTPFSSB(dir->i_sb),ptpfs_data->data.dircache.file_info[x].handle,0); if (ret == PTP_RC_OK) { ptpfs_free_inode_data(dir);//uncache dir->i_version++; return 0; } } } return -EPERM; }
static int ptpfs_open(struct inode *ino, struct file *filp) { //printk(KERN_INFO "%s flags: %X\n", __FUNCTION__, filp->f_flags); struct ptp_data_buffer *data=(struct ptp_data_buffer*)kmalloc(sizeof(struct ptp_data_buffer), GFP_KERNEL); int retval; memset(data,0,sizeof(struct ptp_data_buffer)); switch (filp->f_flags & O_ACCMODE) { case O_RDWR: return -EFAULT; case O_RDONLY: retval = ptp_getobject(PTPFSSB(ino->i_sb),ino->i_ino,data); if (retval == PTP_RC_OK) { filp->private_data = data; return 0; } break; case O_WRONLY: filp->private_data = data; return 0; } kfree(data); return -EFAULT; }
static struct dentry * ptpfs_lookup(struct inode *dir, struct dentry *dentry) { int x; //printk(KERN_INFO "%s\n", __FUNCTION__); struct ptpfs_inode_data* ptpfs_data = PTPFSINO(dir); if (!ptpfs_get_dir_data(dir)) { d_add(dentry, NULL); return NULL; } if (ptpfs_data->type != INO_TYPE_DIR && ptpfs_data->type != INO_TYPE_STGDIR) { d_add(dentry, NULL); return NULL; } for (x = 0; x < ptpfs_data->data.dircache.num_files; x++) { if (!memcmp(ptpfs_data->data.dircache.file_info[x].filename,dentry->d_name.name,dentry->d_name.len)) { struct ptp_object_info object; if (ptp_getobjectinfo(PTPFSSB(dir->i_sb),ptpfs_data->data.dircache.file_info[x].handle,&object)!=PTP_RC_OK) { d_add(dentry, NULL); return NULL; } int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; if (object.object_format==PTP_OFC_Association && object.association_type == PTP_AT_GenericFolder) { mode |= S_IFDIR; } else { mode |= S_IFREG; } struct inode *newi = ptpfs_get_inode(dir->i_sb, mode , 0,ptpfs_data->data.dircache.file_info[x].handle); PTPFSINO(newi)->parent = dir; ptpfs_set_inode_info(newi,&object); //atomic_inc(&newi->i_count); /* New dentry reference */ d_add(dentry, newi); ptp_free_object_info(&object); return NULL; } } d_add(dentry, NULL); return NULL; }
static int ptpfs_mkdir(struct inode *ino,struct dentry *d,int i) { //printk(KERN_INFO "%s %s %d\n",__FUNCTION__,d->d_name.name,i); __u32 storage; __u32 parent; __u32 handle; struct ptp_object_info objectinfo; memset(&objectinfo,0,sizeof(objectinfo)); storage = PTPFSINO(ino)->storage; if (PTPFSINO(ino)->type == INO_TYPE_STGDIR) { parent = 0xffffffff; } else { parent = ino->i_ino; } objectinfo.filename = (unsigned char *)d->d_name.name; objectinfo.object_format=PTP_OFC_Association; objectinfo.association_type = PTP_AT_GenericFolder; int ret = ptp_sendobjectinfo(PTPFSSB(ino->i_sb), &storage, &parent, &handle, &objectinfo); /* if (ret == PTP_RC_OK) { struct ptp_data_buffer data; memset(&data,0,sizeof(data)); ret = ptp_sendobject(PTPFSSB(ino->i_sb),&data,0); } */ objectinfo.filename = NULL; ptp_free_object_info(&objectinfo); if (ret == PTP_RC_OK) { ptpfs_free_inode_data(ino);//uncache ino->i_version++; return 0; } return -EPERM; }
static int ptpfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir) { // printk(KERN_INFO "%s\n", __FUNCTION__); struct inode *inode = filp->f_dentry->d_inode; struct dentry *dentry = filp->f_dentry; struct ptp_storage_ids storageids; int ino; int x; char fsname[256]; int typeCount[5]; memset(typeCount,0,sizeof(typeCount)); memset(&storageids,0,sizeof(storageids)); int offset = filp->f_pos; if (offset) { return 1; } switch (offset) { case 0: if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR) < 0) return 0; offset++; filp->f_pos++; // fall through case 1: spin_lock(&dcache_lock); ino = dentry->d_parent->d_inode->i_ino; spin_unlock(&dcache_lock); if (filldir(dirent, "..", 2, offset, ino, DT_DIR) < 0) break; filp->f_pos++; offset++; default: if (ptp_getstorageids(PTPFSSB(inode->i_sb), &storageids)!=PTP_RC_OK) { printk(KERN_INFO "Error getting storage ids\n"); storageids.n = 0; storageids.storage = NULL; } for (x = 0; x < storageids.n; x++) { struct ptp_storage_info storageinfo; if ((storageids.storage[x]&0x0000ffff)==0) continue; memset(&storageinfo,0,sizeof(storageinfo)); if (ptp_getstorageinfo(PTPFSSB(inode->i_sb), storageids.storage[x],&storageinfo)!=PTP_RC_OK) { printk(KERN_INFO "Error getting storage info\n"); } else { get_root_dir_name(&storageinfo, fsname, typeCount) ; ino = storageids.storage[x]; ptp_free_storage_info(&storageinfo); if (filldir(dirent, fsname, strlen(fsname), filp->f_pos, ino ,DT_DIR) < 0) { ptp_free_storage_ids(&storageids); return 0; } filp->f_pos++; } } ptp_free_storage_ids(&storageids); return 1; } return 0; }
static int ptpfs_create(struct inode *dir,struct dentry *d,int i) { //printk(KERN_INFO "%s %s %d\n",__FUNCTION__,d->d_name.name,i); __u32 storage; __u32 parent; __u32 handle; struct ptp_object_info objectinfo; memset(&objectinfo,0,sizeof(objectinfo)); storage = PTPFSINO(dir)->storage; if (PTPFSINO(dir)->type == INO_TYPE_STGDIR) { parent = 0xffffffff; } else { parent = dir->i_ino; } objectinfo.filename = (unsigned char *)d->d_name.name; objectinfo.object_format=get_format((unsigned char *)d->d_name.name,d->d_name.len); objectinfo.object_compressed_size=0; int ret = ptp_sendobjectinfo(PTPFSSB(dir->i_sb), &storage, &parent, &handle, &objectinfo); if (ret == PTP_RC_OK) { struct ptp_data_buffer data; struct ptp_block block; unsigned char buf[10]; memset(&data,0,sizeof(data)); memset(&block,0,sizeof(block)); data.blocks=█ data.num_blocks = 1; block.block_size = 0; block.block = buf; ret = ptp_sendobject(PTPFSSB(dir->i_sb),&data,0); if (handle == 0) { //problem - it didn't return the right handle - need to do something find it struct ptp_object_handles objects; objects.n = 0; objects.handles = NULL; ptpfs_get_dir_data(dir); if (PTPFSINO(dir)->type == INO_TYPE_DIR) { ptp_getobjecthandles(PTPFSSB(dir->i_sb), PTPFSINO(dir)->storage, 0x000000, dir->i_ino,&objects); } else { ptp_getobjecthandles(PTPFSSB(dir->i_sb), dir->i_ino, 0x000000, 0xffffffff ,&objects); } int x,y; for (x = 0; x < objects.n && !handle; x++ ) { for (y = 0; y < PTPFSINO(dir)->data.dircache.num_files; y++) { if (PTPFSINO(dir)->data.dircache.file_info[y].handle == objects.handles[x]) { objects.handles[x] = 0; y = PTPFSINO(dir)->data.dircache.num_files; } } if (objects.handles[x]) { handle = objects.handles[x]; } } ptp_free_object_handles(&objects); } int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_IFREG; struct inode *newi = ptpfs_get_inode(dir->i_sb, mode , 0,handle); PTPFSINO(newi)->parent = dir; ptpfs_set_inode_info(newi,&objectinfo); atomic_inc(&newi->i_count); /* New dentry reference */ d_instantiate(d, newi); objectinfo.filename = NULL; ptp_free_object_info(&objectinfo); ptpfs_free_inode_data(dir);//uncache dir->i_version++; newi->i_mtime = CURRENT_TIME; return 0; } objectinfo.filename = NULL; ptp_free_object_info(&objectinfo); return -EPERM; }
static int ptpfs_get_dir_data(struct inode *inode) { int x; struct ptpfs_inode_data* ptpfs_data = PTPFSINO(inode); if (ptpfs_data->data.dircache.file_info == NULL) { struct ptp_object_handles objects; objects.n = 0; objects.handles = NULL; ptpfs_free_inode_data(inode); ptpfs_data->data.dircache.num_files = 0; ptpfs_data->data.dircache.file_info = NULL; if (ptpfs_data->type == INO_TYPE_DIR) { if (ptp_getobjecthandles(PTPFSSB(inode->i_sb), ptpfs_data->storage, 0x000000, inode->i_ino,&objects) != PTP_RC_OK) { return 0; } } else { if (ptp_getobjecthandles(PTPFSSB(inode->i_sb), inode->i_ino, 0x000000, 0xffffffff ,&objects) != PTP_RC_OK) { return 0; } } int size = objects.n*sizeof(struct ptpfs_dirinode_fileinfo); struct ptpfs_dirinode_fileinfo* finfo = (struct ptpfs_dirinode_fileinfo*)kmalloc(size, GFP_KERNEL); ptpfs_data->data.dircache.file_info = finfo; if (finfo == NULL) { return 0; } memset(ptpfs_data->data.dircache.file_info,0,size); for (x = 0; x < objects.n; x++) { struct ptp_object_info object; memset(&object,0,sizeof(object)); if (ptp_getobjectinfo(PTPFSSB(inode->i_sb),objects.handles[x],&object)!=PTP_RC_OK) { ptpfs_free_inode_data(inode); ptp_free_object_handles(&objects); return 0; } if (ptpfs_data->type == INO_TYPE_STGDIR && (object.storage_id != inode->i_ino || object.parent_object != 0)) { continue; } int mode = DT_REG; if (object.object_format==PTP_OFC_Association && object.association_type == PTP_AT_GenericFolder) mode = DT_DIR; finfo[ptpfs_data->data.dircache.num_files].filename = object.filename; finfo[ptpfs_data->data.dircache.num_files].handle = objects.handles[x]; finfo[ptpfs_data->data.dircache.num_files].mode = mode; ptpfs_data->data.dircache.num_files++; object.filename = NULL; ptp_free_object_info(&object); } ptp_free_object_handles(&objects); } return 1; }