📄 dir.c
字号:
if (a->len != b->len) goto out; for (i=0; i < a->len; i++) { if (tolower(a->name[i]) != tolower(b->name[i])) goto out; } result = 0;out: return result;}/* * This is the callback from dput() when d_count is going to 0. * We use this to unhash dentries with bad inodes. */static intsmb_delete_dentry(struct dentry * dentry){ if (dentry->d_inode) { if (is_bad_inode(dentry->d_inode)) { PARANOIA("bad inode, unhashing %s/%s\n", DENTRY_PATH(dentry)); return 1; } } else { /* N.B. Unhash negative dentries? */ } return 0;}/* * Initialize a new dentry */voidsmb_new_dentry(struct dentry *dentry){ struct smb_sb_info *server = server_from_dentry(dentry); if (server->mnt->flags & SMB_MOUNT_CASE) dentry->d_op = &smbfs_dentry_operations_case; else dentry->d_op = &smbfs_dentry_operations; dentry->d_time = jiffies;}/* * Whenever a lookup succeeds, we know the parent directories * are all valid, so we want to update the dentry timestamps. * N.B. Move this to dcache? */voidsmb_renew_times(struct dentry * dentry){ dget(dentry); spin_lock(&dentry->d_lock); for (;;) { struct dentry *parent; dentry->d_time = jiffies; if (IS_ROOT(dentry)) break; parent = dentry->d_parent; dget(parent); spin_unlock(&dentry->d_lock); dput(dentry); dentry = parent; spin_lock(&dentry->d_lock); } spin_unlock(&dentry->d_lock); dput(dentry);}static struct dentry *smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){ struct smb_fattr finfo; struct inode *inode; int error; struct smb_sb_info *server; error = -ENAMETOOLONG; if (dentry->d_name.len > SMB_MAXNAMELEN) goto out; /* Do not allow lookup of names with backslashes in */ error = -EINVAL; if (memchr(dentry->d_name.name, '\\', dentry->d_name.len)) goto out; lock_kernel(); error = smb_proc_getattr(dentry, &finfo);#ifdef SMBFS_PARANOIA if (error && error != -ENOENT) PARANOIA("find %s/%s failed, error=%d\n", DENTRY_PATH(dentry), error);#endif inode = NULL; if (error == -ENOENT) goto add_entry; if (!error) { error = -EACCES; finfo.f_ino = iunique(dentry->d_sb, 2); inode = smb_iget(dir->i_sb, &finfo); if (inode) { add_entry: server = server_from_dentry(dentry); if (server->mnt->flags & SMB_MOUNT_CASE) dentry->d_op = &smbfs_dentry_operations_case; else dentry->d_op = &smbfs_dentry_operations; d_add(dentry, inode); smb_renew_times(dentry); error = 0; } } unlock_kernel();out: return ERR_PTR(error);}/* * This code is common to all routines creating a new inode. */static intsmb_instantiate(struct dentry *dentry, __u16 fileid, int have_id){ struct smb_sb_info *server = server_from_dentry(dentry); struct inode *inode; int error; struct smb_fattr fattr; VERBOSE("file %s/%s, fileid=%u\n", DENTRY_PATH(dentry), fileid); error = smb_proc_getattr(dentry, &fattr); if (error) goto out_close; smb_renew_times(dentry); fattr.f_ino = iunique(dentry->d_sb, 2); inode = smb_iget(dentry->d_sb, &fattr); if (!inode) goto out_no_inode; if (have_id) { struct smb_inode_info *ei = SMB_I(inode); ei->fileid = fileid; ei->access = SMB_O_RDWR; ei->open = server->generation; } d_instantiate(dentry, inode);out: return error;out_no_inode: error = -EACCES;out_close: if (have_id) { PARANOIA("%s/%s failed, error=%d, closing %u\n", DENTRY_PATH(dentry), error, fileid); smb_close_fileid(dentry, fileid); } goto out;}/* N.B. How should the mode argument be used? */static intsmb_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd){ struct smb_sb_info *server = server_from_dentry(dentry); __u16 fileid; int error; struct iattr attr; VERBOSE("creating %s/%s, mode=%d\n", DENTRY_PATH(dentry), mode); lock_kernel(); smb_invalid_dir_cache(dir); error = smb_proc_create(dentry, 0, get_seconds(), &fileid); if (!error) { if (server->opt.capabilities & SMB_CAP_UNIX) { /* Set attributes for new file */ attr.ia_valid = ATTR_MODE; attr.ia_mode = mode; error = smb_proc_setattr_unix(dentry, &attr, 0, 0); } error = smb_instantiate(dentry, fileid, 1); } else { PARANOIA("%s/%s failed, error=%d\n", DENTRY_PATH(dentry), error); } unlock_kernel(); return error;}/* N.B. How should the mode argument be used? */static intsmb_mkdir(struct inode *dir, struct dentry *dentry, int mode){ struct smb_sb_info *server = server_from_dentry(dentry); int error; struct iattr attr; lock_kernel(); smb_invalid_dir_cache(dir); error = smb_proc_mkdir(dentry); if (!error) { if (server->opt.capabilities & SMB_CAP_UNIX) { /* Set attributes for new directory */ attr.ia_valid = ATTR_MODE; attr.ia_mode = mode; error = smb_proc_setattr_unix(dentry, &attr, 0, 0); } error = smb_instantiate(dentry, 0, 0); } unlock_kernel(); return error;}static intsmb_rmdir(struct inode *dir, struct dentry *dentry){ struct inode *inode = dentry->d_inode; int error; /* * Close the directory if it's open. */ lock_kernel(); smb_close(inode); /* * Check that nobody else is using the directory.. */ error = -EBUSY; if (!d_unhashed(dentry)) goto out; smb_invalid_dir_cache(dir); error = smb_proc_rmdir(dentry);out: unlock_kernel(); return error;}static intsmb_unlink(struct inode *dir, struct dentry *dentry){ int error; /* * Close the file if it's open. */ lock_kernel(); smb_close(dentry->d_inode); smb_invalid_dir_cache(dir); error = smb_proc_unlink(dentry); if (!error) smb_renew_times(dentry); unlock_kernel(); return error;}static intsmb_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry){ int error; /* * Close any open files, and check whether to delete the * target before attempting the rename. */ lock_kernel(); if (old_dentry->d_inode) smb_close(old_dentry->d_inode); if (new_dentry->d_inode) { smb_close(new_dentry->d_inode); error = smb_proc_unlink(new_dentry); if (error) { VERBOSE("unlink %s/%s, error=%d\n", DENTRY_PATH(new_dentry), error); goto out; } /* FIXME */ d_delete(new_dentry); } smb_invalid_dir_cache(old_dir); smb_invalid_dir_cache(new_dir); error = smb_proc_mv(old_dentry, new_dentry); if (!error) { smb_renew_times(old_dentry); smb_renew_times(new_dentry); }out: unlock_kernel(); return error;}/* * FIXME: samba servers won't let you create device nodes unless uid/gid * matches the connection credentials (and we don't know which those are ...) */static intsmb_make_node(struct inode *dir, struct dentry *dentry, int mode, dev_t dev){ int error; struct iattr attr; attr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID; attr.ia_mode = mode; attr.ia_uid = current->euid; attr.ia_gid = current->egid; if (!new_valid_dev(dev)) return -EINVAL; smb_invalid_dir_cache(dir); error = smb_proc_setattr_unix(dentry, &attr, MAJOR(dev), MINOR(dev)); if (!error) { error = smb_instantiate(dentry, 0, 0); } return error;}/* * dentry = existing file * new_dentry = new file */static intsmb_link(struct dentry *dentry, struct inode *dir, struct dentry *new_dentry){ int error; DEBUG1("smb_link old=%s/%s new=%s/%s\n", DENTRY_PATH(dentry), DENTRY_PATH(new_dentry)); smb_invalid_dir_cache(dir); error = smb_proc_link(server_from_dentry(dentry), dentry, new_dentry); if (!error) { smb_renew_times(dentry); error = smb_instantiate(new_dentry, 0, 0); } return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -