1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/sysv/namei.c 4 * 5 * minix/namei.c 6 * Copyright (C) 1991, 1992 Linus Torvalds 7 * 8 * coh/namei.c 9 * Copyright (C) 1993 Pascal Haible, Bruno Haible 10 * 11 * sysv/namei.c 12 * Copyright (C) 1993 Bruno Haible 13 * Copyright (C) 1997, 1998 Krzysztof G. Baranowski 14 */ 15 16 #include <linux/pagemap.h> 17 #include "sysv.h" 18 19 static int add_nondir(struct dentry *dentry, struct inode *inode) 20 { 21 int err = sysv_add_link(dentry, inode); 22 if (!err) { 23 d_instantiate(dentry, inode); 24 return 0; 25 } 26 inode_dec_link_count(inode); 27 iput(inode); 28 return err; 29 } 30 31 static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags) 32 { 33 struct inode * inode = NULL; 34 ino_t ino; 35 36 if (dentry->d_name.len > SYSV_NAMELEN) 37 return ERR_PTR(-ENAMETOOLONG); 38 ino = sysv_inode_by_name(dentry); 39 if (ino) 40 inode = sysv_iget(dir->i_sb, ino); 41 return d_splice_alias(inode, dentry); 42 } 43 44 static int sysv_mknod(struct user_namespace *mnt_userns, struct inode *dir, 45 struct dentry *dentry, umode_t mode, dev_t rdev) 46 { 47 struct inode * inode; 48 int err; 49 50 if (!old_valid_dev(rdev)) 51 return -EINVAL; 52 53 inode = sysv_new_inode(dir, mode); 54 err = PTR_ERR(inode); 55 56 if (!IS_ERR(inode)) { 57 sysv_set_inode(inode, rdev); 58 mark_inode_dirty(inode); 59 err = add_nondir(dentry, inode); 60 } 61 return err; 62 } 63 64 static int sysv_create(struct user_namespace *mnt_userns, struct inode *dir, 65 struct dentry *dentry, umode_t mode, bool excl) 66 { 67 return sysv_mknod(&init_user_ns, dir, dentry, mode, 0); 68 } 69 70 static int sysv_symlink(struct user_namespace *mnt_userns, struct inode *dir, 71 struct dentry *dentry, const char *symname) 72 { 73 int err = -ENAMETOOLONG; 74 int l = strlen(symname)+1; 75 struct inode * inode; 76 77 if (l > dir->i_sb->s_blocksize) 78 goto out; 79 80 inode = sysv_new_inode(dir, S_IFLNK|0777); 81 err = PTR_ERR(inode); 82 if (IS_ERR(inode)) 83 goto out; 84 85 sysv_set_inode(inode, 0); 86 err = page_symlink(inode, symname, l); 87 if (err) 88 goto out_fail; 89 90 mark_inode_dirty(inode); 91 err = add_nondir(dentry, inode); 92 out: 93 return err; 94 95 out_fail: 96 inode_dec_link_count(inode); 97 iput(inode); 98 goto out; 99 } 100 101 static int sysv_link(struct dentry * old_dentry, struct inode * dir, 102 struct dentry * dentry) 103 { 104 struct inode *inode = d_inode(old_dentry); 105 106 inode->i_ctime = current_time(inode); 107 inode_inc_link_count(inode); 108 ihold(inode); 109 110 return add_nondir(dentry, inode); 111 } 112 113 static int sysv_mkdir(struct user_namespace *mnt_userns, struct inode *dir, 114 struct dentry *dentry, umode_t mode) 115 { 116 struct inode * inode; 117 int err; 118 119 inode_inc_link_count(dir); 120 121 inode = sysv_new_inode(dir, S_IFDIR|mode); 122 err = PTR_ERR(inode); 123 if (IS_ERR(inode)) 124 goto out_dir; 125 126 sysv_set_inode(inode, 0); 127 128 inode_inc_link_count(inode); 129 130 err = sysv_make_empty(inode, dir); 131 if (err) 132 goto out_fail; 133 134 err = sysv_add_link(dentry, inode); 135 if (err) 136 goto out_fail; 137 138 d_instantiate(dentry, inode); 139 out: 140 return err; 141 142 out_fail: 143 inode_dec_link_count(inode); 144 inode_dec_link_count(inode); 145 iput(inode); 146 out_dir: 147 inode_dec_link_count(dir); 148 goto out; 149 } 150 151 static int sysv_unlink(struct inode * dir, struct dentry * dentry) 152 { 153 struct inode * inode = d_inode(dentry); 154 struct page * page; 155 struct sysv_dir_entry * de; 156 int err = -ENOENT; 157 158 de = sysv_find_entry(dentry, &page); 159 if (!de) 160 goto out; 161 162 err = sysv_delete_entry (de, page); 163 if (err) 164 goto out; 165 166 inode->i_ctime = dir->i_ctime; 167 inode_dec_link_count(inode); 168 out: 169 return err; 170 } 171 172 static int sysv_rmdir(struct inode * dir, struct dentry * dentry) 173 { 174 struct inode *inode = d_inode(dentry); 175 int err = -ENOTEMPTY; 176 177 if (sysv_empty_dir(inode)) { 178 err = sysv_unlink(dir, dentry); 179 if (!err) { 180 inode->i_size = 0; 181 inode_dec_link_count(inode); 182 inode_dec_link_count(dir); 183 } 184 } 185 return err; 186 } 187 188 /* 189 * Anybody can rename anything with this: the permission checks are left to the 190 * higher-level routines. 191 */ 192 static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir, 193 struct dentry *old_dentry, struct inode *new_dir, 194 struct dentry *new_dentry, unsigned int flags) 195 { 196 struct inode * old_inode = d_inode(old_dentry); 197 struct inode * new_inode = d_inode(new_dentry); 198 struct page * dir_page = NULL; 199 struct sysv_dir_entry * dir_de = NULL; 200 struct page * old_page; 201 struct sysv_dir_entry * old_de; 202 int err = -ENOENT; 203 204 if (flags & ~RENAME_NOREPLACE) 205 return -EINVAL; 206 207 old_de = sysv_find_entry(old_dentry, &old_page); 208 if (!old_de) 209 goto out; 210 211 if (S_ISDIR(old_inode->i_mode)) { 212 err = -EIO; 213 dir_de = sysv_dotdot(old_inode, &dir_page); 214 if (!dir_de) 215 goto out_old; 216 } 217 218 if (new_inode) { 219 struct page * new_page; 220 struct sysv_dir_entry * new_de; 221 222 err = -ENOTEMPTY; 223 if (dir_de && !sysv_empty_dir(new_inode)) 224 goto out_dir; 225 226 err = -ENOENT; 227 new_de = sysv_find_entry(new_dentry, &new_page); 228 if (!new_de) 229 goto out_dir; 230 sysv_set_link(new_de, new_page, old_inode); 231 new_inode->i_ctime = current_time(new_inode); 232 if (dir_de) 233 drop_nlink(new_inode); 234 inode_dec_link_count(new_inode); 235 } else { 236 err = sysv_add_link(new_dentry, old_inode); 237 if (err) 238 goto out_dir; 239 if (dir_de) 240 inode_inc_link_count(new_dir); 241 } 242 243 sysv_delete_entry(old_de, old_page); 244 mark_inode_dirty(old_inode); 245 246 if (dir_de) { 247 sysv_set_link(dir_de, dir_page, new_dir); 248 inode_dec_link_count(old_dir); 249 } 250 return 0; 251 252 out_dir: 253 if (dir_de) { 254 kunmap(dir_page); 255 put_page(dir_page); 256 } 257 out_old: 258 kunmap(old_page); 259 put_page(old_page); 260 out: 261 return err; 262 } 263 264 /* 265 * directories can handle most operations... 266 */ 267 const struct inode_operations sysv_dir_inode_operations = { 268 .create = sysv_create, 269 .lookup = sysv_lookup, 270 .link = sysv_link, 271 .unlink = sysv_unlink, 272 .symlink = sysv_symlink, 273 .mkdir = sysv_mkdir, 274 .rmdir = sysv_rmdir, 275 .mknod = sysv_mknod, 276 .rename = sysv_rename, 277 .getattr = sysv_getattr, 278 }; 279