Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/ufs/namei.c
0004  *
0005  * Migration to usage of "page cache" on May 2006 by
0006  * Evgeniy Dushistov <dushistov@mail.ru> based on ext2 code base.
0007  *
0008  * Copyright (C) 1998
0009  * Daniel Pirkl <daniel.pirkl@email.cz>
0010  * Charles University, Faculty of Mathematics and Physics
0011  *
0012  *  from
0013  *
0014  *  linux/fs/ext2/namei.c
0015  *
0016  * Copyright (C) 1992, 1993, 1994, 1995
0017  * Remy Card (card@masi.ibp.fr)
0018  * Laboratoire MASI - Institut Blaise Pascal
0019  * Universite Pierre et Marie Curie (Paris VI)
0020  *
0021  *  from
0022  *
0023  *  linux/fs/minix/namei.c
0024  *
0025  *  Copyright (C) 1991, 1992  Linus Torvalds
0026  *
0027  *  Big-endian to little-endian byte-swapping/bitmaps by
0028  *        David S. Miller (davem@caip.rutgers.edu), 1995
0029  */
0030 
0031 #include <linux/time.h>
0032 #include <linux/fs.h>
0033 
0034 #include "ufs_fs.h"
0035 #include "ufs.h"
0036 #include "util.h"
0037 
0038 static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
0039 {
0040     int err = ufs_add_link(dentry, inode);
0041     if (!err) {
0042         d_instantiate_new(dentry, inode);
0043         return 0;
0044     }
0045     inode_dec_link_count(inode);
0046     discard_new_inode(inode);
0047     return err;
0048 }
0049 
0050 static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
0051 {
0052     struct inode * inode = NULL;
0053     ino_t ino;
0054     
0055     if (dentry->d_name.len > UFS_MAXNAMLEN)
0056         return ERR_PTR(-ENAMETOOLONG);
0057 
0058     ino = ufs_inode_by_name(dir, &dentry->d_name);
0059     if (ino)
0060         inode = ufs_iget(dir->i_sb, ino);
0061     return d_splice_alias(inode, dentry);
0062 }
0063 
0064 /*
0065  * By the time this is called, we already have created
0066  * the directory cache entry for the new file, but it
0067  * is so far negative - it has no inode.
0068  *
0069  * If the create succeeds, we fill in the inode information
0070  * with d_instantiate(). 
0071  */
0072 static int ufs_create (struct user_namespace * mnt_userns,
0073         struct inode * dir, struct dentry * dentry, umode_t mode,
0074         bool excl)
0075 {
0076     struct inode *inode;
0077 
0078     inode = ufs_new_inode(dir, mode);
0079     if (IS_ERR(inode))
0080         return PTR_ERR(inode);
0081 
0082     inode->i_op = &ufs_file_inode_operations;
0083     inode->i_fop = &ufs_file_operations;
0084     inode->i_mapping->a_ops = &ufs_aops;
0085     mark_inode_dirty(inode);
0086     return ufs_add_nondir(dentry, inode);
0087 }
0088 
0089 static int ufs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
0090              struct dentry *dentry, umode_t mode, dev_t rdev)
0091 {
0092     struct inode *inode;
0093     int err;
0094 
0095     if (!old_valid_dev(rdev))
0096         return -EINVAL;
0097 
0098     inode = ufs_new_inode(dir, mode);
0099     err = PTR_ERR(inode);
0100     if (!IS_ERR(inode)) {
0101         init_special_inode(inode, mode, rdev);
0102         ufs_set_inode_dev(inode->i_sb, UFS_I(inode), rdev);
0103         mark_inode_dirty(inode);
0104         err = ufs_add_nondir(dentry, inode);
0105     }
0106     return err;
0107 }
0108 
0109 static int ufs_symlink (struct user_namespace * mnt_userns, struct inode * dir,
0110     struct dentry * dentry, const char * symname)
0111 {
0112     struct super_block * sb = dir->i_sb;
0113     int err;
0114     unsigned l = strlen(symname)+1;
0115     struct inode * inode;
0116 
0117     if (l > sb->s_blocksize)
0118         return -ENAMETOOLONG;
0119 
0120     inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
0121     err = PTR_ERR(inode);
0122     if (IS_ERR(inode))
0123         return err;
0124 
0125     if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) {
0126         /* slow symlink */
0127         inode->i_op = &page_symlink_inode_operations;
0128         inode_nohighmem(inode);
0129         inode->i_mapping->a_ops = &ufs_aops;
0130         err = page_symlink(inode, symname, l);
0131         if (err)
0132             goto out_fail;
0133     } else {
0134         /* fast symlink */
0135         inode->i_op = &simple_symlink_inode_operations;
0136         inode->i_link = (char *)UFS_I(inode)->i_u1.i_symlink;
0137         memcpy(inode->i_link, symname, l);
0138         inode->i_size = l-1;
0139     }
0140     mark_inode_dirty(inode);
0141 
0142     return ufs_add_nondir(dentry, inode);
0143 
0144 out_fail:
0145     inode_dec_link_count(inode);
0146     discard_new_inode(inode);
0147     return err;
0148 }
0149 
0150 static int ufs_link (struct dentry * old_dentry, struct inode * dir,
0151     struct dentry *dentry)
0152 {
0153     struct inode *inode = d_inode(old_dentry);
0154     int error;
0155 
0156     inode->i_ctime = current_time(inode);
0157     inode_inc_link_count(inode);
0158     ihold(inode);
0159 
0160     error = ufs_add_link(dentry, inode);
0161     if (error) {
0162         inode_dec_link_count(inode);
0163         iput(inode);
0164     } else
0165         d_instantiate(dentry, inode);
0166     return error;
0167 }
0168 
0169 static int ufs_mkdir(struct user_namespace * mnt_userns, struct inode * dir,
0170     struct dentry * dentry, umode_t mode)
0171 {
0172     struct inode * inode;
0173     int err;
0174 
0175     inode_inc_link_count(dir);
0176 
0177     inode = ufs_new_inode(dir, S_IFDIR|mode);
0178     err = PTR_ERR(inode);
0179     if (IS_ERR(inode))
0180         goto out_dir;
0181 
0182     inode->i_op = &ufs_dir_inode_operations;
0183     inode->i_fop = &ufs_dir_operations;
0184     inode->i_mapping->a_ops = &ufs_aops;
0185 
0186     inode_inc_link_count(inode);
0187 
0188     err = ufs_make_empty(inode, dir);
0189     if (err)
0190         goto out_fail;
0191 
0192     err = ufs_add_link(dentry, inode);
0193     if (err)
0194         goto out_fail;
0195 
0196     d_instantiate_new(dentry, inode);
0197     return 0;
0198 
0199 out_fail:
0200     inode_dec_link_count(inode);
0201     inode_dec_link_count(inode);
0202     discard_new_inode(inode);
0203 out_dir:
0204     inode_dec_link_count(dir);
0205     return err;
0206 }
0207 
0208 static int ufs_unlink(struct inode *dir, struct dentry *dentry)
0209 {
0210     struct inode * inode = d_inode(dentry);
0211     struct ufs_dir_entry *de;
0212     struct page *page;
0213     int err = -ENOENT;
0214 
0215     de = ufs_find_entry(dir, &dentry->d_name, &page);
0216     if (!de)
0217         goto out;
0218 
0219     err = ufs_delete_entry(dir, de, page);
0220     if (err)
0221         goto out;
0222 
0223     inode->i_ctime = dir->i_ctime;
0224     inode_dec_link_count(inode);
0225     err = 0;
0226 out:
0227     return err;
0228 }
0229 
0230 static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
0231 {
0232     struct inode * inode = d_inode(dentry);
0233     int err= -ENOTEMPTY;
0234 
0235     if (ufs_empty_dir (inode)) {
0236         err = ufs_unlink(dir, dentry);
0237         if (!err) {
0238             inode->i_size = 0;
0239             inode_dec_link_count(inode);
0240             inode_dec_link_count(dir);
0241         }
0242     }
0243     return err;
0244 }
0245 
0246 static int ufs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
0247               struct dentry *old_dentry, struct inode *new_dir,
0248               struct dentry *new_dentry, unsigned int flags)
0249 {
0250     struct inode *old_inode = d_inode(old_dentry);
0251     struct inode *new_inode = d_inode(new_dentry);
0252     struct page *dir_page = NULL;
0253     struct ufs_dir_entry * dir_de = NULL;
0254     struct page *old_page;
0255     struct ufs_dir_entry *old_de;
0256     int err = -ENOENT;
0257 
0258     if (flags & ~RENAME_NOREPLACE)
0259         return -EINVAL;
0260 
0261     old_de = ufs_find_entry(old_dir, &old_dentry->d_name, &old_page);
0262     if (!old_de)
0263         goto out;
0264 
0265     if (S_ISDIR(old_inode->i_mode)) {
0266         err = -EIO;
0267         dir_de = ufs_dotdot(old_inode, &dir_page);
0268         if (!dir_de)
0269             goto out_old;
0270     }
0271 
0272     if (new_inode) {
0273         struct page *new_page;
0274         struct ufs_dir_entry *new_de;
0275 
0276         err = -ENOTEMPTY;
0277         if (dir_de && !ufs_empty_dir(new_inode))
0278             goto out_dir;
0279 
0280         err = -ENOENT;
0281         new_de = ufs_find_entry(new_dir, &new_dentry->d_name, &new_page);
0282         if (!new_de)
0283             goto out_dir;
0284         ufs_set_link(new_dir, new_de, new_page, old_inode, 1);
0285         new_inode->i_ctime = current_time(new_inode);
0286         if (dir_de)
0287             drop_nlink(new_inode);
0288         inode_dec_link_count(new_inode);
0289     } else {
0290         err = ufs_add_link(new_dentry, old_inode);
0291         if (err)
0292             goto out_dir;
0293         if (dir_de)
0294             inode_inc_link_count(new_dir);
0295     }
0296 
0297     /*
0298      * Like most other Unix systems, set the ctime for inodes on a
0299      * rename.
0300      */
0301     old_inode->i_ctime = current_time(old_inode);
0302 
0303     ufs_delete_entry(old_dir, old_de, old_page);
0304     mark_inode_dirty(old_inode);
0305 
0306     if (dir_de) {
0307         if (old_dir != new_dir)
0308             ufs_set_link(old_inode, dir_de, dir_page, new_dir, 0);
0309         else {
0310             kunmap(dir_page);
0311             put_page(dir_page);
0312         }
0313         inode_dec_link_count(old_dir);
0314     }
0315     return 0;
0316 
0317 
0318 out_dir:
0319     if (dir_de) {
0320         kunmap(dir_page);
0321         put_page(dir_page);
0322     }
0323 out_old:
0324     kunmap(old_page);
0325     put_page(old_page);
0326 out:
0327     return err;
0328 }
0329 
0330 const struct inode_operations ufs_dir_inode_operations = {
0331     .create     = ufs_create,
0332     .lookup     = ufs_lookup,
0333     .link       = ufs_link,
0334     .unlink     = ufs_unlink,
0335     .symlink    = ufs_symlink,
0336     .mkdir      = ufs_mkdir,
0337     .rmdir      = ufs_rmdir,
0338     .mknod      = ufs_mknod,
0339     .rename     = ufs_rename,
0340 };