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 mnt_idmap *idmap, 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 mnt_idmap *idmap, struct inode *dir, 65 struct dentry *dentry, umode_t mode, bool excl) 66 { 67 return sysv_mknod(&nop_mnt_idmap, dir, dentry, mode, 0); 68 } 69 70 static int sysv_symlink(struct mnt_idmap *idmap, 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_set_ctime_current(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 mnt_idmap *idmap, 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; 157 158 de = sysv_find_entry(dentry, &page); 159 if (!de) 160 return -ENOENT; 161 162 err = sysv_delete_entry(de, page); 163 if (!err) { 164 inode_set_ctime_to_ts(inode, inode_get_ctime(dir)); 165 inode_dec_link_count(inode); 166 } 167 unmap_and_put_page(page, de); 168 return err; 169 } 170 171 static int sysv_rmdir(struct inode * dir, struct dentry * dentry) 172 { 173 struct inode *inode = d_inode(dentry); 174 int err = -ENOTEMPTY; 175 176 if (sysv_empty_dir(inode)) { 177 err = sysv_unlink(dir, dentry); 178 if (!err) { 179 inode->i_size = 0; 180 inode_dec_link_count(inode); 181 inode_dec_link_count(dir); 182 } 183 } 184 return err; 185 } 186 187 /* 188 * Anybody can rename anything with this: the permission checks are left to the 189 * higher-level routines. 190 */ 191 static int sysv_rename(struct mnt_idmap *idmap, struct inode *old_dir, 192 struct dentry *old_dentry, struct inode *new_dir, 193 struct dentry *new_dentry, unsigned int flags) 194 { 195 struct inode * old_inode = d_inode(old_dentry); 196 struct inode * new_inode = d_inode(new_dentry); 197 struct page * dir_page = NULL; 198 struct sysv_dir_entry * dir_de = NULL; 199 struct page * old_page; 200 struct sysv_dir_entry * old_de; 201 int err = -ENOENT; 202 203 if (flags & ~RENAME_NOREPLACE) 204 return -EINVAL; 205 206 old_de = sysv_find_entry(old_dentry, &old_page); 207 if (!old_de) 208 goto out; 209 210 if (S_ISDIR(old_inode->i_mode)) { 211 err = -EIO; 212 dir_de = sysv_dotdot(old_inode, &dir_page); 213 if (!dir_de) 214 goto out_old; 215 } 216 217 if (new_inode) { 218 struct page * new_page; 219 struct sysv_dir_entry * new_de; 220 221 err = -ENOTEMPTY; 222 if (dir_de && !sysv_empty_dir(new_inode)) 223 goto out_dir; 224 225 err = -ENOENT; 226 new_de = sysv_find_entry(new_dentry, &new_page); 227 if (!new_de) 228 goto out_dir; 229 err = sysv_set_link(new_de, new_page, old_inode); 230 unmap_and_put_page(new_page, new_de); 231 if (err) 232 goto out_dir; 233 inode_set_ctime_current(new_inode); 234 if (dir_de) 235 drop_nlink(new_inode); 236 inode_dec_link_count(new_inode); 237 } else { 238 err = sysv_add_link(new_dentry, old_inode); 239 if (err) 240 goto out_dir; 241 if (dir_de) 242 inode_inc_link_count(new_dir); 243 } 244 245 err = sysv_delete_entry(old_de, old_page); 246 if (err) 247 goto out_dir; 248 249 mark_inode_dirty(old_inode); 250 251 if (dir_de) { 252 err = sysv_set_link(dir_de, dir_page, new_dir); 253 if (!err) 254 inode_dec_link_count(old_dir); 255 } 256 257 out_dir: 258 if (dir_de) 259 unmap_and_put_page(dir_page, dir_de); 260 out_old: 261 unmap_and_put_page(old_page, old_de); 262 out: 263 return err; 264 } 265 266 /* 267 * directories can handle most operations... 268 */ 269 const struct inode_operations sysv_dir_inode_operations = { 270 .create = sysv_create, 271 .lookup = sysv_lookup, 272 .link = sysv_link, 273 .unlink = sysv_unlink, 274 .symlink = sysv_symlink, 275 .mkdir = sysv_mkdir, 276 .rmdir = sysv_rmdir, 277 .mknod = sysv_mknod, 278 .rename = sysv_rename, 279 .getattr = sysv_getattr, 280 }; 281
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.