//Call after setting disk.h's 'disk_size' superblock_t minifile_initialize(superblock_t sblock){ int i; inode_t root_inode; inode_t first_inode; block_t first_block; if(DEBUG) printf("minifile_initialize starting...\n"); //CREATE SUPERBLOCK sblock = (superblock_t) malloc(sizeof(struct superblock)); sblock->data.disk_size = disk_size; sblock->data.magic_number = 19540119; //SET UP INODES AND BLOCKS sblock->data.inode_queue_FREE = queue_new(); sblock->data.inode_queue_ACTIVE = queue_new(); sblock->data.block_queue_FREE = queue_new(); sblock->data.block_queue_ACTIVE = queue_new(); if(DEBUG) printf("inode nad block queues created. Their lengths are: %d %d %d %d\n", queue_length(sblock->data.inode_queue_FREE),queue_length(sblock->data.inode_queue_ACTIVE), queue_length(sblock->data.block_queue_FREE),queue_length(sblock->data.block_queue_ACTIVE)); root_inode = create_inode(0); first_inode = create_inode(1); queue_append(sblock->data.inode_queue_ACTIVE,(any_t)root_inode); queue_append(sblock->data.inode_queue_FREE,(any_t)first_inode); for(i=2;i<(0.1*disk_size);i++){ queue_append(sblock->data.inode_queue_FREE,(any_t)create_inode(i)); } first_block = (block_t) malloc(sizeof(struct block)); queue_append(sblock->data.block_queue_FREE,(any_t)first_block); for(i=1;i<(0.9*disk_size-1);i++){ queue_append(sblock->data.block_queue_FREE,(any_t)create_block(i)); } if(DEBUG) printf("inode and block queues created. Their lengths are: %d %d %d %d\n", queue_length(sblock->data.inode_queue_FREE),queue_length(sblock->data.inode_queue_ACTIVE), queue_length(sblock->data.block_queue_FREE),queue_length(sblock->data.block_queue_ACTIVE)); //FINISH SETTING UP SUPERBLOCK sblock->data.root_inode = root_inode; //RETURN SUPERBLOCK return sblock; }
unsigned int create_ifile(enum file_type_e type) { unsigned int inumber; inumber = create_inode(type); ffatal(inumber, "unable to create inode"); return inumber; }
void assign_inode(struct cdfs_entry_struct *entry) { entry->inode=create_inode(); if ( entry->inode ) { entry->inode->alias=entry; } }
/* Get an inode's information and store the inode in the cache * The inode may become invalid after the next call to this function. * Nofile: allow internal inodes */ static int get_inode(long long inode,pinode *inodep,int nofile) { int i,freeone,oldest; unsigned ksusage; static unsigned curusage=1; static char *mftentry=NULL; pinode xinode; /* Space for the MFT entry */ if(!mftentry) { mftentry=malloc(mftentsize); if(!mftentry) return 5; } /* Look if the inode is in the cache; * if no, look for unused cache entries * and find the oldest cache entry */ for(i=oldest=0,freeone=-1,ksusage=0;i<MAXINODEBUF;i++) { if(!inodes[i]) freeone=i; else if(inodes[i]->inode==inode) { inodes[i]->lastusage=curusage++; *inodep=inodes[i]; if(inodes[i]->ftype<0 && !nofile) return 5; return 0; } else if(inodes[i]->lastusage<ksusage || !ksusage) { ksusage=inodes[i]->lastusage; oldest=i; } } /* Which entry to use ? */ if(freeone<0) freeone=oldest; /* Read the inode's MFT entry */ i=read_attribute(mft_inode,0x80,inode*mftentsize,mftentry,mftentsize,0); if(i<0) return -i; if(i!=mftentsize) return 5; if(do_fixups(mftentry,mftentsize)) return 5; xinode=create_inode(inode,mftentry,nofile); if(!xinode) return 5; xinode->lastusage=curusage++; if(inodes[freeone]) { free(inodes[freeone]->curidx); free(inodes[freeone]->treedata); free(inodes[freeone]); } *inodep=inodes[freeone]=xinode; return 0; }
int fatfs_mknod(vnode_t * dir, const char * name, int mode, void * specinfo, vnode_t ** result) { struct fatfs_inode * indir = get_inode_of_vnode(dir); struct fatfs_inode * res = NULL; char * in_fpath; int err; #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "fatfs_mknod(dir %p, name \"%s\", mode %u, specinfo %p, result %p)\n", dir, name, mode, specinfo, result); #endif if (!S_ISDIR(dir->vn_mode)) return -ENOTDIR; if ((mode & S_IFMT) != S_IFREG) return -ENOTSUP; /* FAT only suports regular files. */ if (specinfo) return -EINVAL; /* specinfo not supported. */ in_fpath = format_fpath(indir, name); if (!in_fpath) return -ENOMEM; err = create_inode(&res, get_ffsb_of_sb(dir->sb), in_fpath, hash32_str(in_fpath, 0), O_CREAT); if (err) { kfree(in_fpath); return fresult2errno(err); } if (result) *result = &res->in_vnode; fatfs_chmod(&res->in_vnode, mode); #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "mkdod() ok\n"); #endif return 0; }
static vnode_t * create_root(struct fatfs_sb * fatfs_sb) { char * rootpath; long vn_hash; struct fatfs_inode * in; int err; rootpath = kzalloc(2); if (!rootpath) return NULL; vn_hash = hash32_str(rootpath, 0); err = create_inode(&in, fatfs_sb, rootpath, vn_hash, O_DIRECTORY | O_RDWR); if (err) { KERROR(KERROR_ERR, "Failed to init a root vnode for fatfs (%d)\n", err); return NULL; } in->in_fpath = rootpath; vrefset(&in->in_vnode, 1); return &in->in_vnode; }
static void overlay_mknod(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info, mode_t mode, dev_t rdev) { struct resource_struct *resource=call_info->object->resource; struct localfile_struct *localfile=(struct localfile_struct *) resource->data; struct pathinfo_struct *pathinfo=&call_info->pathinfo; unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len; char path[len0 + len1 + 1]; struct entry_struct *entry=NULL, *parent=pinode->alias; struct inode_struct *inode; memcpy(path, localfile->pathinfo.path, len1); if (len0>0) { memcpy(path+len1, pathinfo->path + call_info->relpath, len0); len1+=len0; } path[len1]='\0'; entry=create_entry(parent, xname); inode=create_inode(); if (entry && inode) { struct entry_struct *result=NULL; unsigned int error=0; entry->inode=inode; inode->alias=entry; result=insert_entry(entry, &error, _ENTRY_FLAG_TEMP); if (result==entry) { uid_t uid_keep=setfsuid(call_info->uid); gid_t gid_keep=setfsgid(call_info->gid); mode_t umask_keep=umask(call_info->umask); mode = (mode & ~call_info->umask); if (mknod(path, mode, rdev)==0) { struct fuse_entry_param e; adjust_pathmax(call_info->pathinfo.len); add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->workspace_mount); /* here complete the insert ?? */ inode->mode=mode; inode->nlink=1; inode->uid=call_info->uid; inode->gid=call_info->gid; inode->nlookup=1; inode->rdev=rdev; inode->size=0; get_current_time(&inode->mtim); memcpy(&inode->ctim, &inode->mtim, sizeof(struct timespec)); memset(&e, 0, sizeof(e)); e.ino = inode->ino; e.generation = 1; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_dev = 0; e.attr.st_uid=inode->uid; e.attr.st_gid=inode->gid; e.attr.st_size=inode->size; e.attr.st_rdev=inode->rdev; memcpy(&e.attr.st_mtim, &inode->mtim, sizeof(struct timespec)); memcpy(&e.attr.st_ctim, &inode->mtim, sizeof(struct timespec)); memcpy(&e.attr.st_atim, &inode->mtim, sizeof(struct timespec)); e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_blksize=4096; e.attr.st_blocks=0; fuse_reply_entry(req, &e); } else { unsigned int error_delete=0; error=errno; remove_entry(entry, &error_delete); destroy_entry(entry); entry=NULL; free(inode); inode=NULL; fuse_reply_err(req, error); } uid_keep=setfsuid(uid_keep); gid_keep=setfsgid(gid_keep); umask_keep=umask(umask_keep); } else { destroy_entry(entry); entry=NULL; free(inode); inode=NULL; if (error==0) error=EEXIST; fuse_reply_err(req, error); } } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } fuse_reply_err(req, ENOMEM); } }
static void overlay_lookup_noncached(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info) { struct resource_struct *resource=call_info->object->resource; struct localfile_struct *localfile=(struct localfile_struct *) resource->data; struct pathinfo_struct *pathinfo=&call_info->pathinfo; unsigned int len0=pathinfo->len - call_info->relpath, len1=localfile->pathinfo.len; char path[len0 + len1 + 1]; struct stat st; memcpy(path, localfile->pathinfo.path, len1); if (len0>0) { memcpy(path+len1, pathinfo->path + call_info->relpath, len0); len1+=len0; } path[len1]='\0'; memset(&st, 0, sizeof(struct stat)); logoutput("overlayfs_lookup_cached, path %s", path); if (lstat(path, &st)==-1) { fuse_reply_err(req, ENOENT); } else { struct entry_struct *entry=NULL, *parent=pinode->alias; struct inode_struct *inode; entry=create_entry(parent, xname); inode=create_inode(); if (entry && inode) { struct fuse_entry_param e; unsigned int error=0; add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->workspace_mount); insert_entry(entry, &error, 0); adjust_pathmax(call_info->pathinfo.len); e.ino = inode->ino; e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_ino = e.ino; e.attr.st_mode = st.st_mode; e.attr.st_nlink = st.st_nlink; e.attr.st_uid = st.st_uid; e.attr.st_gid = st.st_gid; e.attr.st_rdev = st.st_rdev; e.attr.st_atim.tv_sec = st.st_atim.tv_sec; e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec; e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec; e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec; e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec; e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec; e.attr.st_blksize=4096; e.attr.st_blocks=0; inode->mode=st.st_mode; inode->nlink=st.st_nlink; inode->uid=st.st_uid; inode->gid=st.st_gid; inode->rdev=st.st_rdev; if (S_ISDIR(st.st_mode)) { e.attr.st_size = 0; } else { inode->size=st.st_size; e.attr.st_size = st.st_size; } inode->mtim.tv_sec=st.st_mtim.tv_sec; inode->mtim.tv_nsec=st.st_mtim.tv_nsec; inode->ctim.tv_sec=st.st_ctim.tv_sec; inode->ctim.tv_nsec=st.st_ctim.tv_nsec; fuse_reply_entry(req, &e); } else { /* not enough memory to allocate entry and/or inode */ if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } fuse_reply_err(req, ENOMEM); } } free_path_pathinfo(&call_info->pathinfo); }
static void overlay_readdirplus_full(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh) { unsigned int error=0; char *buff=NULL; size_t pos=0; size_t dirent_size; struct fuse_entry_param e; char *name=NULL; struct directory_struct *directory=dh->directory; struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data; struct entry_struct *entry, *result; struct inode_struct *inode; unsigned char dtype; struct name_struct xname={NULL, 0, 0}; int res=0; memset(&e, 0, sizeof(struct fuse_entry_param)); e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_blksize=4096; e.attr.st_blocks=0; buff=malloc(size); if (! buff) { error=ENOMEM; goto error; } if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) { free(buff); buff=NULL; error=EAGAIN; goto error; } while (pos<size) { if (offset==0) { inode=dh->parent->inode; /* the . entry */ e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = 0; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; name = (char *) dotname; inode->nlookup++; } else if (offset==1) { /* the .. entry */ if ( ! dh->parent->parent ) { inode=dh->parent->inode; } else { inode=dh->parent->parent->inode; } e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = 0; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; name = (char *) dotdotname; inode->nlookup++; } else { if (! dh->entry) { readdir: res=get_direntry(overlay_readdir, &xname, &dtype, &error); if (res<=0) { if (res==-1) { free(buff); unlock_directory(directory, _DIRECTORY_LOCK_EXCL); goto error; } dh->mode |= _WORKSPACE_READDIR_MODE_FINISH; break; } if (fstatat(overlay_readdir->fd, xname.name, &e.attr, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)==-1) { goto readdir; } logoutput("overlayfs_readdirplus_real_full: read %s", xname.name); xname.len=strlen(xname.name); calculate_nameindex(&xname); error=0; entry=create_entry(dh->parent, &xname); inode=create_inode(); if (entry && inode) { result=insert_entry_batch(directory, entry, &error, 0); if (result==entry) { memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec)); inode->mode=DTTOIF(dtype); add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount); inode->alias=entry; entry->inode=inode; adjust_pathmax(dh->pathinfo.len + 1 + xname.len); } else { if (error==EEXIST) { destroy_entry(entry); entry=result; memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec)); free(inode); inode=entry->inode; } else { free(buff); destroy_entry(entry); free(inode); goto error; } } e.attr.st_ino=inode->ino; e.ino=inode->ino; e.attr.st_rdev = inode->rdev; e.attr.st_dev = 0; name=entry->name.name; } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } error=ENOMEM; free(buff); goto error; } name=entry->name.name; dh->entry=entry; inode->mode = e.attr.st_mode; inode->nlink = e.attr.st_nlink; inode->uid = e.attr.st_uid; inode->gid = e.attr.st_gid; inode->rdev = e.attr.st_rdev; inode->mtim.tv_sec = e.attr.st_mtim.tv_sec; inode->mtim.tv_nsec = e.attr.st_mtim.tv_nsec; inode->ctim.tv_sec = e.attr.st_ctim.tv_sec; inode->ctim.tv_nsec = e.attr.st_ctim.tv_nsec; if (S_ISDIR(e.attr.st_mode)) { e.attr.st_size=0; } else { inode->size=e.attr.st_size; } } else { entry=dh->entry; inode=entry->inode; name=entry->name.name; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; if (S_ISDIR(inode->mode)) { e.attr.st_size = 0; } else { e.attr.st_size = inode->size; } e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; inode->nlookup++; } e.ino = inode->ino; e.attr.st_ino = e.ino; } dirent_size=fuse_add_direntry_plus(req, buff+pos, size-pos, name, &e, offset+1); if (pos + dirent_size > size) { dh->offset=offset+1; break; } /* increase counter and clear the various fields */ dh->entry=NULL; /* forget current entry to force readdir */ offset++; pos += dirent_size; } unlock_directory(directory, _DIRECTORY_LOCK_EXCL); fuse_reply_buf(req, buff, pos); free(buff); buff=NULL; return; error: fuse_reply_err(req, error); }
static void overlay_readdir_full(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh) { unsigned int error=0; char *buff=NULL; size_t pos=0; size_t dirent_size; struct stat st; char *name=NULL; struct directory_struct *directory=dh->directory; struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data; struct entry_struct *entry, *result; struct inode_struct *inode; struct name_struct xname={NULL, 0, 0}; unsigned char dtype=0; int res; memset(&st, 0, sizeof(struct stat)); buff=malloc(size); if (! buff) { error=ENOMEM; goto error; } if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) { free(buff); buff=NULL; error=EAGAIN; goto error; } while (pos<size) { if (offset==0) { inode=dh->parent->inode; /* the . entry */ st.st_ino = inode->ino; st.st_mode = S_IFDIR; name = (char *) dotname; } else if (offset==1) { /* the .. entry */ if ( ! dh->parent->parent ) { inode=dh->parent->inode; st.st_ino = inode->ino; } else { struct entry_struct *parent=dh->parent->parent; inode=parent->inode; st.st_ino=inode->ino; } st.st_mode = S_IFDIR; name = (char *) dotdotname; } else { if (! dh->entry) { readdir: res=get_direntry(overlay_readdir, &xname, &dtype, &error); if (res<=0) { if (res==-1) { free(buff); unlock_directory(directory, _DIRECTORY_LOCK_EXCL); goto error; } dh->mode |= _WORKSPACE_READDIR_MODE_FINISH; break; } xname.len=strlen(xname.name); calculate_nameindex(&xname); error=0; entry=create_entry(dh->parent, &xname); inode=create_inode(); if (entry && inode) { result=insert_entry_batch(directory, entry, &error, 0); if (result==entry) { entry->inode->mode=DTTOIF(dtype); add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount); inode->alias=entry; entry->inode=inode; adjust_pathmax(dh->pathinfo.len + 1 + xname.len); } else { if (error==EEXIST) { destroy_entry(entry); entry=result; free(inode); inode=entry->inode; } else { free(buff); destroy_entry(entry); free(inode); goto error; } } st.st_mode=entry->inode->mode; st.st_ino=entry->inode->ino; name=entry->name.name; } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } error=ENOMEM; free(buff); goto error; } dh->entry=entry; } else { entry=dh->entry; st.st_ino=entry->inode->ino; st.st_mode=entry->inode->mode; name=entry->name.name; } } dirent_size=fuse_add_direntry(req, buff+pos, size-pos, name, &st, offset+1); if (pos + dirent_size > size) { dh->offset = offset + 1; break; } /* increase counter and clear the various fields */ dh->entry=NULL; /* forget current entry to force readdir */ offset++; pos += dirent_size; } unlock_directory(directory, _DIRECTORY_LOCK_EXCL); fuse_reply_buf(req, buff, pos); free(buff); buff=NULL; return; error: fuse_reply_err(req, error); }
/** * Lookup for a vnode (file/dir) in FatFs. * First lookup form vfs_hash and if not found then read it from ff which will * probably read it via devfs interface. After the vnode has been created it * will be added to the vfs hashmap. In ff terminology all files and directories * that are in hashmap are also open on a file/dir handle, thus we'll have to * make sure we don't have too many vnodes in cache that have no references, to * avoid hitting any ff hard limits. */ static int fatfs_lookup(vnode_t * dir, const char * name, vnode_t ** result) { struct fatfs_inode * indir = get_inode_of_vnode(dir); struct fatfs_sb * sb = get_ffsb_of_sb(dir->sb); char * in_fpath; long vn_hash; struct vnode * vn = NULL; int err, retval = 0; KASSERT(dir != NULL, "dir must be set"); /* Format full path */ in_fpath = format_fpath(indir, name); if (!in_fpath) return -ENOMEM; /* * Emulate . and .. */ if (name[0] == '.' && name[1] != '.') { #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "Lookup emulating \".\"\n"); #endif (void)vref(dir); *result = dir; kfree(in_fpath); return 0; } else if (name[0] == '.' && name[1] == '.' && name[2] != '.') { #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "Lookup emulating \"..\"\n"); #endif if (VN_IS_FSROOT(dir)) { *result = dir->sb->mountpoint; kfree(in_fpath); return -EDOM; } else { size_t i = strlenn(in_fpath, NAME_MAX) - 4; while (in_fpath[i] != '/') { i--; } in_fpath[i] = '\0'; } } /* * Lookup from vfs_hash */ vn_hash = hash32_str(in_fpath, 0); err = vfs_hash_get( dir->sb, /* FS superblock */ vn_hash, /* Hash */ &vn, /* Retval */ fatfs_vncmp, /* Comparator */ in_fpath /* Compared fpath */ ); if (err) { retval = -EIO; goto fail; } if (vn) { /* found it in vfs_hash */ #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "vn found in vfs_hash (%p)\n", vn); #endif *result = vn; retval = 0; } else { /* not cached */ struct fatfs_inode * in; #ifdef configFATFS_DEBUG KERROR(KERROR_DEBUG, "vn not in vfs_hash\n"); #endif /* * Create a inode and fetch data from the device. * This also vrefs. */ err = create_inode(&in, sb, in_fpath, vn_hash, O_RDWR); if (err) { retval = err; goto fail; } in_fpath = NULL; /* shall not be freed. */ *result = &in->in_vnode; retval = 0; } fail: kfree(in_fpath); return retval; }
static void workspace_nfs_mknod(fuse_req_t req, struct inode_struct *pinode, struct name_struct *xname, struct call_info_struct *call_info, mode_t mode, dev_t rdev) { struct resource_struct *resource=call_info->object->resource; struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data; struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data; char *path=call_info->pathinfo.path + call_info->relpath; struct entry_struct *entry=NULL, *parent=pinode->alias; struct inode_struct *inode; logoutput("workspace_nfs_mknod, path %s", path); entry=create_entry(parent, xname); inode=create_inode(); if (entry && inode) { int result=0; inode->alias=entry; entry->inode=inode; pthread_mutex_lock(&nfs_export->mutex); result=nfs_mknod(nfs_ctx, path, mode, rdev); pthread_mutex_unlock(&nfs_export->mutex); if (result==0) { struct fuse_entry_param e; unsigned int error=0; struct stat st; memset(&st, 0, sizeof(struct stat)); add_inode_hashtable(inode, increase_inodes_workspace, (void *) call_info->object->workspace_mount); insert_entry(entry, &error, 0); adjust_pathmax(call_info->pathinfo.len); pthread_mutex_lock(&nfs_export->mutex); nfs_chmod(nfs_ctx, path, mode); nfs_stat(nfs_ctx, path, &st); pthread_mutex_unlock(&nfs_export->mutex); inode->nlookup=1; inode->mode=st.st_mode; inode->nlink=st.st_nlink; inode->uid=st.st_uid; inode->gid=st.st_gid; inode->rdev=st.st_rdev; inode->size=st.st_size; inode->mtim.tv_sec=st.st_mtim.tv_sec; inode->mtim.tv_nsec=st.st_mtim.tv_nsec; inode->ctim.tv_sec=st.st_ctim.tv_sec; inode->ctim.tv_nsec=st.st_ctim.tv_nsec; e.ino = inode->ino; e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_ino = e.ino; e.attr.st_mode = st.st_mode; e.attr.st_nlink = st.st_nlink; e.attr.st_uid = st.st_uid; e.attr.st_gid = st.st_gid; e.attr.st_rdev = st.st_rdev; e.attr.st_atim.tv_sec = st.st_atim.tv_sec; e.attr.st_atim.tv_nsec = st.st_atim.tv_nsec; e.attr.st_mtim.tv_sec = st.st_mtim.tv_sec; e.attr.st_mtim.tv_nsec = st.st_mtim.tv_nsec; e.attr.st_ctim.tv_sec = st.st_ctim.tv_sec; e.attr.st_ctim.tv_nsec = st.st_ctim.tv_nsec; e.attr.st_blksize=_DEFAULT_BLOCKSIZE; if (inode->size % e.attr.st_blksize == 0) { e.attr.st_blocks=inode->size / e.attr.st_blksize; } else { e.attr.st_blocks=1 + inode->size / e.attr.st_blksize; } fuse_reply_entry(req, &e); } else { /* error nfs create */ destroy_entry(entry); free(inode); fuse_reply_err(req, abs(result)); } } else { /* not enough memory to allocate entry and/or inode */ if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } fuse_reply_err(req, ENOMEM); } free_path_pathinfo(&call_info->pathinfo); }
static void workspace_nfs_readdirplus_simple(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh) { struct resource_struct *resource=dh->object->resource; struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data; struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data; unsigned int error=0; char *buff=NULL; size_t pos=0; size_t dirent_size; struct fuse_entry_param e; char *name=NULL; struct directory_struct *directory=dh->directory; struct nfsdir *dir=(struct nfsdir *) dh->handle.data; struct entry_struct *entry, *result; struct inode_struct *inode; struct name_struct xname={NULL, 0, 0}; memset(&e, 0, sizeof(struct fuse_entry_param)); e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_blksize=_DEFAULT_BLOCKSIZE; buff=malloc(size); if (! buff) { error=ENOMEM; goto error; } if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) { free(buff); buff=NULL; error=EAGAIN; goto error; } while (pos<size) { if (offset==0) { inode=dh->parent->inode; /* the . entry */ e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = inode->size; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; name = (char *) dotname; inode->nlookup++; } else if (offset==1) { /* the .. entry */ if ( ! dh->parent->parent ) { inode=dh->parent->inode; } else { inode=dh->parent->parent->inode; } e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = inode->size; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; name = (char *) dotdotname; inode->nlookup++; } else { if (! dh->entry) { struct nfsdirent *de; readdir: pthread_mutex_lock(&nfs_export->mutex); de=nfs_readdir(nfs_ctx, dir); pthread_mutex_unlock(&nfs_export->mutex); if (de) { if (strcmp(de->name, ".")==0 || strcmp(de->name, "..")==0) continue; xname.name=de->name; xname.len=strlen(xname.name); calculate_nameindex(&xname); } else { dh->mode |= _WORKSPACE_READDIR_MODE_FINISH; break; } error=0; entry=create_entry(dh->parent, &xname); inode=create_inode(); if (entry && inode) { result=insert_entry_batch(directory, entry, &error, 0); if (result==entry) { struct workspace_object_struct *export_object=NULL; inode->mode = translate_libnfs_type(de->type); inode->mode |= de->mode; add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount); inode->alias=entry; entry->inode=inode; memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec)); inode->nlookup++; inode->nlink=2; inode->uid=0; /* ?? */ inode->gid=0; /* ?? */ inode->size=de->size; /* struct timeval convert to timespec */ inode->mtim.tv_sec=de->mtime.tv_sec; inode->mtim.tv_nsec=1000 * de->mtime.tv_usec; inode->ctim.tv_sec=de->ctime.tv_sec; inode->ctim.tv_nsec=1000 * de->ctime.tv_usec; adjust_pathmax(dh->pathinfo.len + 1 + xname.len); } else { if (error==EEXIST) { destroy_entry(entry); entry=result; memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec)); free(inode); inode=entry->inode; } else { free(buff); destroy_entry(entry); free(inode); goto error; } } } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } error=ENOMEM; free(buff); goto error; } name=entry->name.name; dh->entry=entry; } else { entry=dh->entry; inode=entry->inode; name=entry->name.name; } e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = inode->size; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; if (inode->size % e.attr.st_blksize == 0) { e.attr.st_blocks=inode->size / e.attr.st_blksize; } else { e.attr.st_blocks=1 + inode->size / e.attr.st_blksize; } } dirent_size=fuse_add_direntry_plus(req, buff+pos, size-pos, name, &e, offset+1); if (pos + dirent_size > size) { dh->offset=offset; break; } /* increase counter and clear the various fields */ dh->entry=NULL; /* forget current entry to force readdir */ offset++; pos += dirent_size; } unlock_directory(directory, _DIRECTORY_LOCK_EXCL); fuse_reply_buf(req, buff, pos); free(buff); buff=NULL; return; error: fuse_reply_err(req, error); }
static void workspace_nfs_readdir_simple(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh) { struct resource_struct *resource=dh->object->resource; struct net_nfs_export_struct *nfs_export=(struct net_nfs_export_struct *) resource->data; struct nfs_context *nfs_ctx=(struct nfs_context *) nfs_export->data; unsigned int error=0; char *buff=NULL; size_t pos=0; size_t dirent_size; char *name=NULL; struct directory_struct *directory=dh->directory; struct nfsdir *dir=(struct nfsdir *) dh->handle.data; struct entry_struct *entry, *result; struct inode_struct *inode; struct name_struct xname={NULL, 0, 0}; struct stat st; memset(&st, 0, sizeof(struct stat)); buff=malloc(size); if (! buff) { error=ENOMEM; goto error; } if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) { free(buff); buff=NULL; error=EAGAIN; goto error; } while (pos<size) { if (offset==0) { inode=dh->parent->inode; /* the . entry */ st.st_ino = inode->ino; st.st_mode = S_IFDIR; name = (char *) dotname; } else if (offset==1) { /* the .. entry */ if (! dh->parent->parent ) { inode=dh->parent->inode; st.st_ino = inode->ino; } else { struct entry_struct *parent=dh->parent->parent; inode=parent->inode; st.st_ino=inode->ino; } st.st_mode = S_IFDIR; name = (char *) dotdotname; } else { if (! dh->entry) { struct nfsdirent *de; readdir: pthread_mutex_lock(&nfs_export->mutex); de=nfs_readdir(nfs_ctx, dir); pthread_mutex_unlock(&nfs_export->mutex); if (de) { if (strcmp(de->name, ".")==0 || strcmp(de->name, "..")==0) continue; xname.name=de->name; xname.len=strlen(xname.name); calculate_nameindex(&xname); } else { dh->mode |= _WORKSPACE_READDIR_MODE_FINISH; break; } error=0; entry=create_entry(dh->parent, &xname); inode=create_inode(); if (entry && inode) { result=insert_entry_batch(directory, entry, &error, 0); if (result==entry) { struct workspace_object_struct *export_object=NULL; inode->mode = translate_libnfs_type(de->type); inode->mode |= de->mode; add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount); inode->alias=entry; entry->inode=inode; adjust_pathmax(dh->pathinfo.len + 1 + xname.len); } else { if (error==EEXIST) { destroy_entry(entry); entry=result; free(inode); inode=entry->inode; } else { free(buff); destroy_entry(entry); free(inode); goto error; } } st.st_mode=entry->inode->mode; st.st_ino=entry->inode->ino; name=entry->name.name; } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } error=ENOMEM; free(buff); goto error; } dh->entry=entry; } else { st.st_ino=dh->entry->inode->ino; st.st_mode=dh->entry->inode->mode; name=dh->entry->name.name; } } dirent_size=fuse_add_direntry(req, buff+pos, size-pos, name, &st, offset+1); if (pos + dirent_size > size) { dh->offset = offset + 1; break; } /* increase counter and clear the various fields */ dh->entry=NULL; /* forget current entry to force readdir */ offset++; pos += dirent_size; } unlock_directory(directory, _DIRECTORY_LOCK_EXCL); fuse_reply_buf(req, buff, pos); free(buff); buff=NULL; return; error: fuse_reply_err(req, error); }
/* Initialize the NTFS access */ int ntfs_initialize(long long offset, int partmode, int dosnames) { unsigned char sec[512],*mftfirst; unsigned u,u2; long long ll; void *pold; /* Check for a partition table */ part_offset = offset; llseek(dskhandle, part_offset, SEEK_SET); read(dskhandle, sec, 512); if(partmode == 2) partmode = memcmp(&(sec[3]),"NTFS ",8)?1:0; if(partmode) { part_offset+=getlittle32(sec,0x1C6)*512; llseek(dskhandle,part_offset,SEEK_SET); read(dskhandle,sec,512); } /* Is it really NTFS ? */ if(memcmp(&(sec[3]),"NTFS ",8)) { fprintf(stderr,"This is not an NTFS disk/image.\n"); return (1); } usedosnames=dosnames; sectlen=sec[11]+0x100*sec[12]; clustlen=sec[13]*sectlen; ll=getlittle64(sec,0x28); mftclust=getlittle64(sec,0x30); if(ll>0x7FFFFFFF) disksize=0x7FFFFFFF; else disksize=(unsigned)ll; /* Now get the data MFT entry for the MFT itself */ llseek(dskhandle,part_offset+clustlen*mftclust,SEEK_SET); mftfirst=malloc(clustlen); if(!mftfirst) { fprintf(stderr,"Memory problem.\n"); return (1); } read(dskhandle,mftfirst,clustlen); mftentsize=getlittle32(mftfirst,0x1C); if(mftentsize>clustlen) { pold=mftfirst; mftfirst=realloc(mftfirst,mftentsize); if(!mftfirst) { free(pold); fprintf(stderr,"Memory problem.\n"); return (1); } read(dskhandle,mftfirst+clustlen,mftentsize-clustlen); } if(do_fixups(mftfirst,mftentsize)) { free(mftfirst); fprintf(stderr,"Error: MFT seems to be damaged.\n"); return (1); } mft_inode=create_inode(0,mftfirst,0); if(!mft_inode) { fprintf(stderr,"Error: Couldn\'t get the MFT inode.\n"); return (1); } free(mftfirst); /* Initialize the cache */ for(u=0;u<MAXCLUSTBUF;u++) { clusters[u].lastusage=0; clusters[u].cluster=-2ll; clusters[u].data=malloc(clustlen); if(!clusters[u].data) { for(u2=0;u2<u;u2++) free(clusters[u2].data); free(mft_inode); fprintf(stderr,"Not enough memory."); return (1); } } for(u=0;u<MAXINODEBUF;u++) inodes[u]=NULL; return 0; }