static int dev_rmdir(const char *name) { struct nameidata nd; struct dentry *dentry; int err; err = kern_path_parent(name, &nd); if (err) return err; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { if (dentry->d_inode->i_private == &thread) err = vfs_rmdir(nd.path.dentry->d_inode, dentry); else err = -EPERM; } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); return err; }
static int handle_remove(const char *nodename, struct device *dev) { struct nameidata nd; struct dentry *dentry; struct kstat stat; int deleted = 1; int err; err = kern_path_parent(nodename, &nd); if (err) return err; mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len); if (!IS_ERR(dentry)) { if (dentry->d_inode) { err = vfs_getattr(nd.path.mnt, dentry, &stat); if (!err && dev_mynode(dev, dentry->d_inode, &stat)) { struct iattr newattrs; /* * before unlinking this node, reset permissions * of possible references like hardlinks */ newattrs.ia_uid = 0; newattrs.ia_gid = 0; newattrs.ia_mode = stat.mode & ~0777; newattrs.ia_valid = ATTR_UID|ATTR_GID|ATTR_MODE; mutex_lock(&dentry->d_inode->i_mutex); notify_change(dentry, &newattrs); mutex_unlock(&dentry->d_inode->i_mutex); err = vfs_unlink(nd.path.dentry->d_inode, dentry); if (!err || err == -ENOENT) deleted = 1; } } else { err = -ENOENT; } dput(dentry); } else { err = PTR_ERR(dentry); } mutex_unlock(&nd.path.dentry->d_inode->i_mutex); path_put(&nd.path); if (deleted && strchr(nodename, '/')) delete_path(nodename); return err; }
int file_mkdir(const char * pathname, unsigned short perms, int recurse) { /* Welcome to the jungle... */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41) /* DO NOT REFERENCE THIS VARIABLE */ /* It only exists to provide version compatibility */ struct path tmp_path; #endif struct path * path_ptr = NULL; struct dentry * dentry; int ret = 0; if (recurse != 0) { return mkdir_recursive(pathname, perms); } /* Before Linux 3.1 this was somewhat more difficult */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41) { struct nameidata nd; // I'm not 100% sure about the version here, but it was around this time that the API changed #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) ret = kern_path_parent(pathname, &nd); #else if (path_lookup(pathname, LOOKUP_DIRECTORY | LOOKUP_FOLLOW, &nd) == 0) { return 0; } if (path_lookup(pathname, LOOKUP_PARENT | LOOKUP_FOLLOW, &nd) != 0) { return -1; } #endif if (ret != 0) { printk(KERN_ERR "%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__, pathname); return -1; } dentry = lookup_create(&nd, 1); path_ptr = &(nd.path); } #else { dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1); if (IS_ERR(dentry)) { return 0; } path_ptr = &tmp_path; } #endif if (!IS_ERR(dentry)) { ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms); } mutex_unlock(&(path_ptr->dentry->d_inode->i_mutex)); path_put(path_ptr); return ret; }
/* * Safely creates '/proc/systemtap' (if necessary) and * '/proc/systemtap/{module_name}'. * * NB: this function is suitable to call from early in the the * module-init function, and doesn't rely on any other facilities * in our runtime. PR19833. See also PR15408. */ static int _stp_mkdir_proc_module(void) { int found = 0; static char proc_root_name[STP_MODULE_NAME_LEN + sizeof("systemtap/")]; #if defined(STAPCONF_PATH_LOOKUP) || defined(STAPCONF_KERN_PATH_PARENT) struct nameidata nd; #else /* STAPCONF_VFS_PATH_LOOKUP or STAPCONF_KERN_PATH */ struct path path; #if defined(STAPCONF_VFS_PATH_LOOKUP) struct vfsmount *mnt; #endif int rc; #endif /* STAPCONF_VFS_PATH_LOOKUP or STAPCONF_KERN_PATH */ if (_stp_proc_root != NULL) return 0; #if defined(STAPCONF_PATH_LOOKUP) || defined(STAPCONF_KERN_PATH_PARENT) /* Why "/proc/systemtap/foo"? kern_path_parent() is basically * the same thing as calling the old path_lookup() with flags * set to LOOKUP_PARENT, which means to look up the parent of * the path, which in this case is "/proc/systemtap". */ if (! kern_path_parent("/proc/systemtap/foo", &nd)) { found = 1; #ifdef STAPCONF_NAMEIDATA_CLEANUP path_put(&nd.path); #else /* !STAPCONF_NAMEIDATA_CLEANUP */ path_release(&nd); #endif /* !STAPCONF_NAMEIDATA_CLEANUP */ } #elif defined(STAPCONF_KERN_PATH) /* Prefer kern_path() over vfs_path_lookup(), since on some * kernels the declaration for vfs_path_lookup() was moved to * a private header. */ /* See if '/proc/systemtap' exists. */ rc = kern_path("/proc/systemtap", 0, &path); if (rc == 0) { found = 1; path_put (&path); } #else /* STAPCONF_VFS_PATH_LOOKUP */ /* See if '/proc/systemtap' exists. */ if (! init_pid_ns.proc_mnt) { errk("Unable to create '/proc/systemap':" " '/proc' doesn't exist.\n"); goto done; } mnt = init_pid_ns.proc_mnt; rc = vfs_path_lookup(mnt->mnt_root, mnt, "systemtap", 0, &path); if (rc == 0) { found = 1; path_put (&path); } #endif /* STAPCONF_VFS_PATH_LOOKUP */ /* If we couldn't find "/proc/systemtap", create it. */ if (!found) { struct proc_dir_entry *de; de = proc_mkdir ("systemtap", NULL); if (de == NULL) { errk("Unable to create '/proc/systemap':" " proc_mkdir failed.\n"); goto done; } } /* Create the "systemtap/{module_name} directory in procfs. */ strlcpy(proc_root_name, "systemtap/", sizeof(proc_root_name)); strlcat(proc_root_name, THIS_MODULE->name, sizeof(proc_root_name)); _stp_proc_root = proc_mkdir(proc_root_name, NULL); #ifdef STAPCONF_PROCFS_OWNER if (_stp_proc_root != NULL) _stp_proc_root->owner = THIS_MODULE; #endif if (_stp_proc_root == NULL) errk("Unable to create '/proc/systemap/%s':" " proc_mkdir failed.\n", THIS_MODULE->name); done: return (_stp_proc_root) ? 0 : -EINVAL; }