root/fs/minix/namei.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. add_nondir
  2. minix_lookup
  3. minix_mknod
  4. minix_tmpfile
  5. minix_create
  6. minix_symlink
  7. minix_link
  8. minix_mkdir
  9. minix_unlink
  10. minix_rmdir
  11. minix_rename

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  linux/fs/minix/namei.c
   4  *
   5  *  Copyright (C) 1991, 1992  Linus Torvalds
   6  */
   7 
   8 #include "minix.h"
   9 
  10 static int add_nondir(struct dentry *dentry, struct inode *inode)
  11 {
  12         int err = minix_add_link(dentry, inode);
  13         if (!err) {
  14                 d_instantiate(dentry, inode);
  15                 return 0;
  16         }
  17         inode_dec_link_count(inode);
  18         iput(inode);
  19         return err;
  20 }
  21 
  22 static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
  23 {
  24         struct inode * inode = NULL;
  25         ino_t ino;
  26 
  27         if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen)
  28                 return ERR_PTR(-ENAMETOOLONG);
  29 
  30         ino = minix_inode_by_name(dentry);
  31         if (ino)
  32                 inode = minix_iget(dir->i_sb, ino);
  33         return d_splice_alias(inode, dentry);
  34 }
  35 
  36 static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev)
  37 {
  38         int error;
  39         struct inode *inode;
  40 
  41         if (!old_valid_dev(rdev))
  42                 return -EINVAL;
  43 
  44         inode = minix_new_inode(dir, mode, &error);
  45 
  46         if (inode) {
  47                 minix_set_inode(inode, rdev);
  48                 mark_inode_dirty(inode);
  49                 error = add_nondir(dentry, inode);
  50         }
  51         return error;
  52 }
  53 
  54 static int minix_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
  55 {
  56         int error;
  57         struct inode *inode = minix_new_inode(dir, mode, &error);
  58         if (inode) {
  59                 minix_set_inode(inode, 0);
  60                 mark_inode_dirty(inode);
  61                 d_tmpfile(dentry, inode);
  62         }
  63         return error;
  64 }
  65 
  66 static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode,
  67                 bool excl)
  68 {
  69         return minix_mknod(dir, dentry, mode, 0);
  70 }
  71 
  72 static int minix_symlink(struct inode * dir, struct dentry *dentry,
  73           const char * symname)
  74 {
  75         int err = -ENAMETOOLONG;
  76         int i = strlen(symname)+1;
  77         struct inode * inode;
  78 
  79         if (i > dir->i_sb->s_blocksize)
  80                 goto out;
  81 
  82         inode = minix_new_inode(dir, S_IFLNK | 0777, &err);
  83         if (!inode)
  84                 goto out;
  85 
  86         minix_set_inode(inode, 0);
  87         err = page_symlink(inode, symname, i);
  88         if (err)
  89                 goto out_fail;
  90 
  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 minix_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         return add_nondir(dentry, inode);
 110 }
 111 
 112 static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode)
 113 {
 114         struct inode * inode;
 115         int err;
 116 
 117         inode_inc_link_count(dir);
 118 
 119         inode = minix_new_inode(dir, S_IFDIR | mode, &err);
 120         if (!inode)
 121                 goto out_dir;
 122 
 123         minix_set_inode(inode, 0);
 124 
 125         inode_inc_link_count(inode);
 126 
 127         err = minix_make_empty(inode, dir);
 128         if (err)
 129                 goto out_fail;
 130 
 131         err = minix_add_link(dentry, inode);
 132         if (err)
 133                 goto out_fail;
 134 
 135         d_instantiate(dentry, inode);
 136 out:
 137         return err;
 138 
 139 out_fail:
 140         inode_dec_link_count(inode);
 141         inode_dec_link_count(inode);
 142         iput(inode);
 143 out_dir:
 144         inode_dec_link_count(dir);
 145         goto out;
 146 }
 147 
 148 static int minix_unlink(struct inode * dir, struct dentry *dentry)
 149 {
 150         int err = -ENOENT;
 151         struct inode * inode = d_inode(dentry);
 152         struct page * page;
 153         struct minix_dir_entry * de;
 154 
 155         de = minix_find_entry(dentry, &page);
 156         if (!de)
 157                 goto end_unlink;
 158 
 159         err = minix_delete_entry(de, page);
 160         if (err)
 161                 goto end_unlink;
 162 
 163         inode->i_ctime = dir->i_ctime;
 164         inode_dec_link_count(inode);
 165 end_unlink:
 166         return err;
 167 }
 168 
 169 static int minix_rmdir(struct inode * dir, struct dentry *dentry)
 170 {
 171         struct inode * inode = d_inode(dentry);
 172         int err = -ENOTEMPTY;
 173 
 174         if (minix_empty_dir(inode)) {
 175                 err = minix_unlink(dir, dentry);
 176                 if (!err) {
 177                         inode_dec_link_count(dir);
 178                         inode_dec_link_count(inode);
 179                 }
 180         }
 181         return err;
 182 }
 183 
 184 static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
 185                         struct inode * new_dir, struct dentry *new_dentry,
 186                         unsigned int flags)
 187 {
 188         struct inode * old_inode = d_inode(old_dentry);
 189         struct inode * new_inode = d_inode(new_dentry);
 190         struct page * dir_page = NULL;
 191         struct minix_dir_entry * dir_de = NULL;
 192         struct page * old_page;
 193         struct minix_dir_entry * old_de;
 194         int err = -ENOENT;
 195 
 196         if (flags & ~RENAME_NOREPLACE)
 197                 return -EINVAL;
 198 
 199         old_de = minix_find_entry(old_dentry, &old_page);
 200         if (!old_de)
 201                 goto out;
 202 
 203         if (S_ISDIR(old_inode->i_mode)) {
 204                 err = -EIO;
 205                 dir_de = minix_dotdot(old_inode, &dir_page);
 206                 if (!dir_de)
 207                         goto out_old;
 208         }
 209 
 210         if (new_inode) {
 211                 struct page * new_page;
 212                 struct minix_dir_entry * new_de;
 213 
 214                 err = -ENOTEMPTY;
 215                 if (dir_de && !minix_empty_dir(new_inode))
 216                         goto out_dir;
 217 
 218                 err = -ENOENT;
 219                 new_de = minix_find_entry(new_dentry, &new_page);
 220                 if (!new_de)
 221                         goto out_dir;
 222                 minix_set_link(new_de, new_page, old_inode);
 223                 new_inode->i_ctime = current_time(new_inode);
 224                 if (dir_de)
 225                         drop_nlink(new_inode);
 226                 inode_dec_link_count(new_inode);
 227         } else {
 228                 err = minix_add_link(new_dentry, old_inode);
 229                 if (err)
 230                         goto out_dir;
 231                 if (dir_de)
 232                         inode_inc_link_count(new_dir);
 233         }
 234 
 235         minix_delete_entry(old_de, old_page);
 236         mark_inode_dirty(old_inode);
 237 
 238         if (dir_de) {
 239                 minix_set_link(dir_de, dir_page, new_dir);
 240                 inode_dec_link_count(old_dir);
 241         }
 242         return 0;
 243 
 244 out_dir:
 245         if (dir_de) {
 246                 kunmap(dir_page);
 247                 put_page(dir_page);
 248         }
 249 out_old:
 250         kunmap(old_page);
 251         put_page(old_page);
 252 out:
 253         return err;
 254 }
 255 
 256 /*
 257  * directories can handle most operations...
 258  */
 259 const struct inode_operations minix_dir_inode_operations = {
 260         .create         = minix_create,
 261         .lookup         = minix_lookup,
 262         .link           = minix_link,
 263         .unlink         = minix_unlink,
 264         .symlink        = minix_symlink,
 265         .mkdir          = minix_mkdir,
 266         .rmdir          = minix_rmdir,
 267         .mknod          = minix_mknod,
 268         .rename         = minix_rename,
 269         .getattr        = minix_getattr,
 270         .tmpfile        = minix_tmpfile,
 271 };

/* [<][>][^][v][top][bottom][index][help] */