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