📄 dir.c
字号:
{ return; } dir->nused -= 1; i = dir; }}voidsmb_init_root(struct smb_server *server){ struct smb_inode_info *root = &(server->root); root->state = SMB_INODE_LOOKED_UP; root->nused = 1; root->dir = NULL; root->next = root->prev = root; return;}voidsmb_free_all_inodes(struct smb_server *server){ /* Here nothing should be to do. I do not know whether it's better to leave some memory allocated or be stuck in an endless loop */#if 1 struct smb_inode_info *root = &(server->root); if (root->next != root) { printk("smb_free_all_inodes: INODES LEFT!!!\n"); } while (root->next != root) { printk("smb_free_all_inodes: freeing inode\n"); smb_free_inode_info(root->next); /* In case we have an endless loop.. */ schedule(); }#endif return;}/* This has to be called when a connection has gone down, so that all file-handles we got from the server are invalid */voidsmb_invalidate_all_inodes(struct smb_server *server){ struct smb_inode_info *ino = &(server->root); do { ino->finfo.opened = 0; ino = ino->next; } while (ino != &(server->root)); return;}static intcompare_filename(const struct smb_server *server, const char *s1, int len, struct smb_dirent *entry){ if (len != entry->len) {#if 0 /* Check whether the entry is about to be removed */ if (!entry->len) printk("SMBFS: dead entry %s\n", entry->name);#endif return 1; } if (server->case_handling == CASE_DEFAULT) { return strncasecmp(s1, entry->name, len); } return strncmp(s1, entry->name, len);}/* * Search for the smb_inode_info that belongs to this name, * currently by a complete linear search through the inodes * belonging to this filesystem. * * Note that this returns files as well as directories. */static struct smb_inode_info *smb_find_dir_inode(struct inode *parent, const char *name, int len){ struct smb_server *server = SMB_SERVER(parent); struct smb_inode_info *dir = SMB_INOP(parent); struct smb_inode_info *result = &(server->root); if (name == NULL) { return NULL; } if ((len == 1) && (name[0] == '.')) { return dir; } if ((len == 2) && (name[0] == '.') && (name[1] == '.')) { return dir->dir; } do { if (result->dir == dir) { if (compare_filename(server, name, len, &(result->finfo)) == 0) { return result; } } result = result->next; } while (result != &(server->root)); return NULL;}static intsmb_lookup(struct inode *dir, const char *name, int len, struct inode **result){ struct smb_dirent finfo; struct smb_inode_info *result_info; int error; int found_in_cache; struct smb_inode_info *new_inode_info = NULL; *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("smb_lookup: inode is NULL or not a directory.\n"); iput(dir); return -ENOENT; } DDPRINTK("smb_lookup: %s\n", name); /* Fast cheat for . */ if (len == 0 || (len == 1 && name[0] == '.')) { *result = dir; return 0; } /* ..and for .. */ if (len == 2 && name[0] == '.' && name[1] == '.') { struct smb_inode_info *parent = SMB_INOP(dir)->dir; if (parent->state == SMB_INODE_CACHED) { parent->state = SMB_INODE_LOOKED_UP; } *result = iget(dir->i_sb, smb_info_ino(parent)); iput(dir); if (*result == 0) { return -EACCES; } return 0; } result_info = smb_find_dir_inode(dir, name, len); in_tree: if (result_info != NULL) { if (result_info->state == SMB_INODE_CACHED) { result_info->state = SMB_INODE_LOOKED_UP; } *result = iget(dir->i_sb, smb_info_ino(result_info)); iput(dir); if (new_inode_info != NULL) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); } if (*result == NULL) { return -EACCES; } return 0; } /* If the file is in the dir cache, we do not have to ask the server. */ found_in_cache = 0; if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0)) { int first = c_last_returned_index; int i; i = first; do { if (compare_filename(SMB_SERVER(dir), name, len, &(c_entry[i])) == 0) { finfo = c_entry[i]; found_in_cache = 1; break; } i = (i + 1) % c_size; } while (i != first); } if (found_in_cache == 0) { DPRINTK("smb_lookup: not found in cache: %s\n", name); if (len > SMB_MAXNAMELEN) { iput(dir); return -ENAMETOOLONG; } error = smb_proc_getattr(dir, name, len, &finfo); if (error < 0) { iput(dir); return error; } finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); } new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), GFP_KERNEL); /* Here somebody else might have inserted the inode */ result_info = smb_find_dir_inode(dir, name, len); if (result_info != NULL) { goto in_tree; } if (new_inode_info == NULL) { iput(dir); return -ENOMEM; } new_inode_info->finfo = finfo; DPRINTK("attr: %x\n", finfo.attr); if ((*result = smb_iget(dir, new_inode_info)) == NULL) { iput(dir); return -EACCES; } DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info); iput(dir); return 0;}static intsmb_create(struct inode *dir, const char *name, int len, int mode, struct inode **result){ int error; struct smb_dirent entry; struct smb_inode_info *new_inode_info; *result = NULL; if (!dir || !S_ISDIR(dir->i_mode)) { printk("smb_create: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info), GFP_KERNEL); if (new_inode_info == NULL) { iput(dir); return -ENOMEM; } error = smb_proc_create(dir, name, len, 0, CURRENT_TIME); if (error < 0) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); iput(dir); return error; } smb_invalid_dir_cache(dir->i_ino); if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0) { smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info)); iput(dir); return error; } entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1); new_inode_info->finfo = entry; if ((*result = smb_iget(dir, new_inode_info)) == NULL) { iput(dir); return error; } iput(dir); return 0;}static intsmb_mkdir(struct inode *dir, const char *name, int len, int mode){ int error; if (!dir || !S_ISDIR(dir->i_mode)) { iput(dir); return -EINVAL; } if ((error = smb_proc_mkdir(dir, name, len)) == 0) { smb_invalid_dir_cache(dir->i_ino); } iput(dir); return error;}static intsmb_rmdir(struct inode *dir, const char *name, int len){ int error; if (!dir || !S_ISDIR(dir->i_mode)) { printk("smb_rmdir: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (smb_find_dir_inode(dir, name, len) != NULL) { error = -EBUSY; } else { if ((error = smb_proc_rmdir(dir, name, len)) == 0) { smb_invalid_dir_cache(dir->i_ino); } } iput(dir); return error;}static intsmb_unlink(struct inode *dir, const char *name, int len){ int error; if (!dir || !S_ISDIR(dir->i_mode)) { printk("smb_unlink: inode is NULL or not a directory\n"); iput(dir); return -ENOENT; } if (smb_find_dir_inode(dir, name, len) != NULL) { error = -EBUSY; } else { if ((error = smb_proc_unlink(dir, name, len)) == 0) { smb_invalid_dir_cache(dir->i_ino); } } iput(dir); return error;}static intsmb_rename(struct inode *old_dir, const char *old_name, int old_len, struct inode *new_dir, const char *new_name, int new_len, int must_be_dir){ int res; if (!old_dir || !S_ISDIR(old_dir->i_mode)) { printk("smb_rename: old inode is NULL or not a directory\n"); res = -ENOENT; goto finished; } if (!new_dir || !S_ISDIR(new_dir->i_mode)) { printk("smb_rename: new inode is NULL or not a directory\n"); res = -ENOENT; goto finished; } if ((smb_find_dir_inode(old_dir, old_name, old_len) != NULL) || (smb_find_dir_inode(new_dir, new_name, new_len) != NULL)) { res = -EBUSY; goto finished; } res = smb_proc_mv(old_dir, old_name, old_len, new_dir, new_name, new_len); if (res == -EEXIST) { int res1 = smb_proc_unlink(old_dir, new_name, new_len); if (res1 == 0) { res = smb_proc_mv(old_dir, old_name, old_len, new_dir, new_name, new_len); } } if (res == 0) { smb_invalid_dir_cache(old_dir->i_ino); smb_invalid_dir_cache(new_dir->i_ino); } finished: iput(old_dir); iput(new_dir); return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -