Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/fs/minix/namei.c
0004  *
0005  *  Copyright (C) 1991, 1992  Linus Torvalds
0006  */
0007 
0008 #include "minix.h"
0009 
0010 static int add_nondir(struct dentry *dentry, struct inode *inode)
0011 {
0012     int err = minix_add_link(dentry, inode);
0013     if (!err) {
0014         d_instantiate(dentry, inode);
0015         return 0;
0016     }
0017     inode_dec_link_count(inode);
0018     iput(inode);
0019     return err;
0020 }
0021 
0022 static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
0023 {
0024     struct inode * inode = NULL;
0025     ino_t ino;
0026 
0027     if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen)
0028         return ERR_PTR(-ENAMETOOLONG);
0029 
0030     ino = minix_inode_by_name(dentry);
0031     if (ino)
0032         inode = minix_iget(dir->i_sb, ino);
0033     return d_splice_alias(inode, dentry);
0034 }
0035 
0036 static int minix_mknod(struct user_namespace *mnt_userns, struct inode *dir,
0037                struct dentry *dentry, umode_t mode, dev_t rdev)
0038 {
0039     int error;
0040     struct inode *inode;
0041 
0042     if (!old_valid_dev(rdev))
0043         return -EINVAL;
0044 
0045     inode = minix_new_inode(dir, mode, &error);
0046 
0047     if (inode) {
0048         minix_set_inode(inode, rdev);
0049         mark_inode_dirty(inode);
0050         error = add_nondir(dentry, inode);
0051     }
0052     return error;
0053 }
0054 
0055 static int minix_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
0056              struct dentry *dentry, umode_t mode)
0057 {
0058     int error;
0059     struct inode *inode = minix_new_inode(dir, mode, &error);
0060     if (inode) {
0061         minix_set_inode(inode, 0);
0062         mark_inode_dirty(inode);
0063         d_tmpfile(dentry, inode);
0064     }
0065     return error;
0066 }
0067 
0068 static int minix_create(struct user_namespace *mnt_userns, struct inode *dir,
0069             struct dentry *dentry, umode_t mode, bool excl)
0070 {
0071     return minix_mknod(mnt_userns, dir, dentry, mode, 0);
0072 }
0073 
0074 static int minix_symlink(struct user_namespace *mnt_userns, struct inode *dir,
0075              struct dentry *dentry, const char *symname)
0076 {
0077     int err = -ENAMETOOLONG;
0078     int i = strlen(symname)+1;
0079     struct inode * inode;
0080 
0081     if (i > dir->i_sb->s_blocksize)
0082         goto out;
0083 
0084     inode = minix_new_inode(dir, S_IFLNK | 0777, &err);
0085     if (!inode)
0086         goto out;
0087 
0088     minix_set_inode(inode, 0);
0089     err = page_symlink(inode, symname, i);
0090     if (err)
0091         goto out_fail;
0092 
0093     err = add_nondir(dentry, inode);
0094 out:
0095     return err;
0096 
0097 out_fail:
0098     inode_dec_link_count(inode);
0099     iput(inode);
0100     goto out;
0101 }
0102 
0103 static int minix_link(struct dentry * old_dentry, struct inode * dir,
0104     struct dentry *dentry)
0105 {
0106     struct inode *inode = d_inode(old_dentry);
0107 
0108     inode->i_ctime = current_time(inode);
0109     inode_inc_link_count(inode);
0110     ihold(inode);
0111     return add_nondir(dentry, inode);
0112 }
0113 
0114 static int minix_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
0115                struct dentry *dentry, umode_t mode)
0116 {
0117     struct inode * inode;
0118     int err;
0119 
0120     inode_inc_link_count(dir);
0121 
0122     inode = minix_new_inode(dir, S_IFDIR | mode, &err);
0123     if (!inode)
0124         goto out_dir;
0125 
0126     minix_set_inode(inode, 0);
0127 
0128     inode_inc_link_count(inode);
0129 
0130     err = minix_make_empty(inode, dir);
0131     if (err)
0132         goto out_fail;
0133 
0134     err = minix_add_link(dentry, inode);
0135     if (err)
0136         goto out_fail;
0137 
0138     d_instantiate(dentry, inode);
0139 out:
0140     return err;
0141 
0142 out_fail:
0143     inode_dec_link_count(inode);
0144     inode_dec_link_count(inode);
0145     iput(inode);
0146 out_dir:
0147     inode_dec_link_count(dir);
0148     goto out;
0149 }
0150 
0151 static int minix_unlink(struct inode * dir, struct dentry *dentry)
0152 {
0153     int err = -ENOENT;
0154     struct inode * inode = d_inode(dentry);
0155     struct page * page;
0156     struct minix_dir_entry * de;
0157 
0158     de = minix_find_entry(dentry, &page);
0159     if (!de)
0160         goto end_unlink;
0161 
0162     err = minix_delete_entry(de, page);
0163     if (err)
0164         goto end_unlink;
0165 
0166     inode->i_ctime = dir->i_ctime;
0167     inode_dec_link_count(inode);
0168 end_unlink:
0169     return err;
0170 }
0171 
0172 static int minix_rmdir(struct inode * dir, struct dentry *dentry)
0173 {
0174     struct inode * inode = d_inode(dentry);
0175     int err = -ENOTEMPTY;
0176 
0177     if (minix_empty_dir(inode)) {
0178         err = minix_unlink(dir, dentry);
0179         if (!err) {
0180             inode_dec_link_count(dir);
0181             inode_dec_link_count(inode);
0182         }
0183     }
0184     return err;
0185 }
0186 
0187 static int minix_rename(struct user_namespace *mnt_userns,
0188             struct inode *old_dir, struct dentry *old_dentry,
0189             struct inode *new_dir, struct dentry *new_dentry,
0190             unsigned int flags)
0191 {
0192     struct inode * old_inode = d_inode(old_dentry);
0193     struct inode * new_inode = d_inode(new_dentry);
0194     struct page * dir_page = NULL;
0195     struct minix_dir_entry * dir_de = NULL;
0196     struct page * old_page;
0197     struct minix_dir_entry * old_de;
0198     int err = -ENOENT;
0199 
0200     if (flags & ~RENAME_NOREPLACE)
0201         return -EINVAL;
0202 
0203     old_de = minix_find_entry(old_dentry, &old_page);
0204     if (!old_de)
0205         goto out;
0206 
0207     if (S_ISDIR(old_inode->i_mode)) {
0208         err = -EIO;
0209         dir_de = minix_dotdot(old_inode, &dir_page);
0210         if (!dir_de)
0211             goto out_old;
0212     }
0213 
0214     if (new_inode) {
0215         struct page * new_page;
0216         struct minix_dir_entry * new_de;
0217 
0218         err = -ENOTEMPTY;
0219         if (dir_de && !minix_empty_dir(new_inode))
0220             goto out_dir;
0221 
0222         err = -ENOENT;
0223         new_de = minix_find_entry(new_dentry, &new_page);
0224         if (!new_de)
0225             goto out_dir;
0226         minix_set_link(new_de, new_page, old_inode);
0227         new_inode->i_ctime = current_time(new_inode);
0228         if (dir_de)
0229             drop_nlink(new_inode);
0230         inode_dec_link_count(new_inode);
0231     } else {
0232         err = minix_add_link(new_dentry, old_inode);
0233         if (err)
0234             goto out_dir;
0235         if (dir_de)
0236             inode_inc_link_count(new_dir);
0237     }
0238 
0239     minix_delete_entry(old_de, old_page);
0240     mark_inode_dirty(old_inode);
0241 
0242     if (dir_de) {
0243         minix_set_link(dir_de, dir_page, new_dir);
0244         inode_dec_link_count(old_dir);
0245     }
0246     return 0;
0247 
0248 out_dir:
0249     if (dir_de) {
0250         kunmap(dir_page);
0251         put_page(dir_page);
0252     }
0253 out_old:
0254     kunmap(old_page);
0255     put_page(old_page);
0256 out:
0257     return err;
0258 }
0259 
0260 /*
0261  * directories can handle most operations...
0262  */
0263 const struct inode_operations minix_dir_inode_operations = {
0264     .create     = minix_create,
0265     .lookup     = minix_lookup,
0266     .link       = minix_link,
0267     .unlink     = minix_unlink,
0268     .symlink    = minix_symlink,
0269     .mkdir      = minix_mkdir,
0270     .rmdir      = minix_rmdir,
0271     .mknod      = minix_mknod,
0272     .rename     = minix_rename,
0273     .getattr    = minix_getattr,
0274     .tmpfile    = minix_tmpfile,
0275 };