Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  linux/fs/minix/dir.c
0004  *
0005  *  Copyright (C) 1991, 1992 Linus Torvalds
0006  *
0007  *  minix directory handling functions
0008  *
0009  *  Updated to filesystem version 3 by Daniel Aragones
0010  */
0011 
0012 #include "minix.h"
0013 #include <linux/buffer_head.h>
0014 #include <linux/highmem.h>
0015 #include <linux/swap.h>
0016 
0017 typedef struct minix_dir_entry minix_dirent;
0018 typedef struct minix3_dir_entry minix3_dirent;
0019 
0020 static int minix_readdir(struct file *, struct dir_context *);
0021 
0022 const struct file_operations minix_dir_operations = {
0023     .llseek     = generic_file_llseek,
0024     .read       = generic_read_dir,
0025     .iterate_shared = minix_readdir,
0026     .fsync      = generic_file_fsync,
0027 };
0028 
0029 static inline void dir_put_page(struct page *page)
0030 {
0031     kunmap(page);
0032     put_page(page);
0033 }
0034 
0035 /*
0036  * Return the offset into page `page_nr' of the last valid
0037  * byte in that page, plus one.
0038  */
0039 static unsigned
0040 minix_last_byte(struct inode *inode, unsigned long page_nr)
0041 {
0042     unsigned last_byte = PAGE_SIZE;
0043 
0044     if (page_nr == (inode->i_size >> PAGE_SHIFT))
0045         last_byte = inode->i_size & (PAGE_SIZE - 1);
0046     return last_byte;
0047 }
0048 
0049 static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
0050 {
0051     struct address_space *mapping = page->mapping;
0052     struct inode *dir = mapping->host;
0053     int err = 0;
0054     block_write_end(NULL, mapping, pos, len, len, page, NULL);
0055 
0056     if (pos+len > dir->i_size) {
0057         i_size_write(dir, pos+len);
0058         mark_inode_dirty(dir);
0059     }
0060     if (IS_DIRSYNC(dir))
0061         err = write_one_page(page);
0062     else
0063         unlock_page(page);
0064     return err;
0065 }
0066 
0067 static struct page * dir_get_page(struct inode *dir, unsigned long n)
0068 {
0069     struct address_space *mapping = dir->i_mapping;
0070     struct page *page = read_mapping_page(mapping, n, NULL);
0071     if (!IS_ERR(page))
0072         kmap(page);
0073     return page;
0074 }
0075 
0076 static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
0077 {
0078     return (void*)((char*)de + sbi->s_dirsize);
0079 }
0080 
0081 static int minix_readdir(struct file *file, struct dir_context *ctx)
0082 {
0083     struct inode *inode = file_inode(file);
0084     struct super_block *sb = inode->i_sb;
0085     struct minix_sb_info *sbi = minix_sb(sb);
0086     unsigned chunk_size = sbi->s_dirsize;
0087     unsigned long npages = dir_pages(inode);
0088     unsigned long pos = ctx->pos;
0089     unsigned offset;
0090     unsigned long n;
0091 
0092     ctx->pos = pos = ALIGN(pos, chunk_size);
0093     if (pos >= inode->i_size)
0094         return 0;
0095 
0096     offset = pos & ~PAGE_MASK;
0097     n = pos >> PAGE_SHIFT;
0098 
0099     for ( ; n < npages; n++, offset = 0) {
0100         char *p, *kaddr, *limit;
0101         struct page *page = dir_get_page(inode, n);
0102 
0103         if (IS_ERR(page))
0104             continue;
0105         kaddr = (char *)page_address(page);
0106         p = kaddr+offset;
0107         limit = kaddr + minix_last_byte(inode, n) - chunk_size;
0108         for ( ; p <= limit; p = minix_next_entry(p, sbi)) {
0109             const char *name;
0110             __u32 inumber;
0111             if (sbi->s_version == MINIX_V3) {
0112                 minix3_dirent *de3 = (minix3_dirent *)p;
0113                 name = de3->name;
0114                 inumber = de3->inode;
0115             } else {
0116                 minix_dirent *de = (minix_dirent *)p;
0117                 name = de->name;
0118                 inumber = de->inode;
0119             }
0120             if (inumber) {
0121                 unsigned l = strnlen(name, sbi->s_namelen);
0122                 if (!dir_emit(ctx, name, l,
0123                           inumber, DT_UNKNOWN)) {
0124                     dir_put_page(page);
0125                     return 0;
0126                 }
0127             }
0128             ctx->pos += chunk_size;
0129         }
0130         dir_put_page(page);
0131     }
0132     return 0;
0133 }
0134 
0135 static inline int namecompare(int len, int maxlen,
0136     const char * name, const char * buffer)
0137 {
0138     if (len < maxlen && buffer[len])
0139         return 0;
0140     return !memcmp(name, buffer, len);
0141 }
0142 
0143 /*
0144  *  minix_find_entry()
0145  *
0146  * finds an entry in the specified directory with the wanted name. It
0147  * returns the cache buffer in which the entry was found, and the entry
0148  * itself (as a parameter - res_dir). It does NOT read the inode of the
0149  * entry - you'll have to do that yourself if you want to.
0150  */
0151 minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
0152 {
0153     const char * name = dentry->d_name.name;
0154     int namelen = dentry->d_name.len;
0155     struct inode * dir = d_inode(dentry->d_parent);
0156     struct super_block * sb = dir->i_sb;
0157     struct minix_sb_info * sbi = minix_sb(sb);
0158     unsigned long n;
0159     unsigned long npages = dir_pages(dir);
0160     struct page *page = NULL;
0161     char *p;
0162 
0163     char *namx;
0164     __u32 inumber;
0165     *res_page = NULL;
0166 
0167     for (n = 0; n < npages; n++) {
0168         char *kaddr, *limit;
0169 
0170         page = dir_get_page(dir, n);
0171         if (IS_ERR(page))
0172             continue;
0173 
0174         kaddr = (char*)page_address(page);
0175         limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize;
0176         for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
0177             if (sbi->s_version == MINIX_V3) {
0178                 minix3_dirent *de3 = (minix3_dirent *)p;
0179                 namx = de3->name;
0180                 inumber = de3->inode;
0181             } else {
0182                 minix_dirent *de = (minix_dirent *)p;
0183                 namx = de->name;
0184                 inumber = de->inode;
0185             }
0186             if (!inumber)
0187                 continue;
0188             if (namecompare(namelen, sbi->s_namelen, name, namx))
0189                 goto found;
0190         }
0191         dir_put_page(page);
0192     }
0193     return NULL;
0194 
0195 found:
0196     *res_page = page;
0197     return (minix_dirent *)p;
0198 }
0199 
0200 int minix_add_link(struct dentry *dentry, struct inode *inode)
0201 {
0202     struct inode *dir = d_inode(dentry->d_parent);
0203     const char * name = dentry->d_name.name;
0204     int namelen = dentry->d_name.len;
0205     struct super_block * sb = dir->i_sb;
0206     struct minix_sb_info * sbi = minix_sb(sb);
0207     struct page *page = NULL;
0208     unsigned long npages = dir_pages(dir);
0209     unsigned long n;
0210     char *kaddr, *p;
0211     minix_dirent *de;
0212     minix3_dirent *de3;
0213     loff_t pos;
0214     int err;
0215     char *namx = NULL;
0216     __u32 inumber;
0217 
0218     /*
0219      * We take care of directory expansion in the same loop
0220      * This code plays outside i_size, so it locks the page
0221      * to protect that region.
0222      */
0223     for (n = 0; n <= npages; n++) {
0224         char *limit, *dir_end;
0225 
0226         page = dir_get_page(dir, n);
0227         err = PTR_ERR(page);
0228         if (IS_ERR(page))
0229             goto out;
0230         lock_page(page);
0231         kaddr = (char*)page_address(page);
0232         dir_end = kaddr + minix_last_byte(dir, n);
0233         limit = kaddr + PAGE_SIZE - sbi->s_dirsize;
0234         for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
0235             de = (minix_dirent *)p;
0236             de3 = (minix3_dirent *)p;
0237             if (sbi->s_version == MINIX_V3) {
0238                 namx = de3->name;
0239                 inumber = de3->inode;
0240             } else {
0241                 namx = de->name;
0242                 inumber = de->inode;
0243             }
0244             if (p == dir_end) {
0245                 /* We hit i_size */
0246                 if (sbi->s_version == MINIX_V3)
0247                     de3->inode = 0;
0248                 else
0249                     de->inode = 0;
0250                 goto got_it;
0251             }
0252             if (!inumber)
0253                 goto got_it;
0254             err = -EEXIST;
0255             if (namecompare(namelen, sbi->s_namelen, name, namx))
0256                 goto out_unlock;
0257         }
0258         unlock_page(page);
0259         dir_put_page(page);
0260     }
0261     BUG();
0262     return -EINVAL;
0263 
0264 got_it:
0265     pos = page_offset(page) + p - (char *)page_address(page);
0266     err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
0267     if (err)
0268         goto out_unlock;
0269     memcpy (namx, name, namelen);
0270     if (sbi->s_version == MINIX_V3) {
0271         memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4);
0272         de3->inode = inode->i_ino;
0273     } else {
0274         memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2);
0275         de->inode = inode->i_ino;
0276     }
0277     err = dir_commit_chunk(page, pos, sbi->s_dirsize);
0278     dir->i_mtime = dir->i_ctime = current_time(dir);
0279     mark_inode_dirty(dir);
0280 out_put:
0281     dir_put_page(page);
0282 out:
0283     return err;
0284 out_unlock:
0285     unlock_page(page);
0286     goto out_put;
0287 }
0288 
0289 int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
0290 {
0291     struct inode *inode = page->mapping->host;
0292     char *kaddr = page_address(page);
0293     loff_t pos = page_offset(page) + (char*)de - kaddr;
0294     struct minix_sb_info *sbi = minix_sb(inode->i_sb);
0295     unsigned len = sbi->s_dirsize;
0296     int err;
0297 
0298     lock_page(page);
0299     err = minix_prepare_chunk(page, pos, len);
0300     if (err == 0) {
0301         if (sbi->s_version == MINIX_V3)
0302             ((minix3_dirent *) de)->inode = 0;
0303         else
0304             de->inode = 0;
0305         err = dir_commit_chunk(page, pos, len);
0306     } else {
0307         unlock_page(page);
0308     }
0309     dir_put_page(page);
0310     inode->i_ctime = inode->i_mtime = current_time(inode);
0311     mark_inode_dirty(inode);
0312     return err;
0313 }
0314 
0315 int minix_make_empty(struct inode *inode, struct inode *dir)
0316 {
0317     struct page *page = grab_cache_page(inode->i_mapping, 0);
0318     struct minix_sb_info *sbi = minix_sb(inode->i_sb);
0319     char *kaddr;
0320     int err;
0321 
0322     if (!page)
0323         return -ENOMEM;
0324     err = minix_prepare_chunk(page, 0, 2 * sbi->s_dirsize);
0325     if (err) {
0326         unlock_page(page);
0327         goto fail;
0328     }
0329 
0330     kaddr = kmap_atomic(page);
0331     memset(kaddr, 0, PAGE_SIZE);
0332 
0333     if (sbi->s_version == MINIX_V3) {
0334         minix3_dirent *de3 = (minix3_dirent *)kaddr;
0335 
0336         de3->inode = inode->i_ino;
0337         strcpy(de3->name, ".");
0338         de3 = minix_next_entry(de3, sbi);
0339         de3->inode = dir->i_ino;
0340         strcpy(de3->name, "..");
0341     } else {
0342         minix_dirent *de = (minix_dirent *)kaddr;
0343 
0344         de->inode = inode->i_ino;
0345         strcpy(de->name, ".");
0346         de = minix_next_entry(de, sbi);
0347         de->inode = dir->i_ino;
0348         strcpy(de->name, "..");
0349     }
0350     kunmap_atomic(kaddr);
0351 
0352     err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
0353 fail:
0354     put_page(page);
0355     return err;
0356 }
0357 
0358 /*
0359  * routine to check that the specified directory is empty (for rmdir)
0360  */
0361 int minix_empty_dir(struct inode * inode)
0362 {
0363     struct page *page = NULL;
0364     unsigned long i, npages = dir_pages(inode);
0365     struct minix_sb_info *sbi = minix_sb(inode->i_sb);
0366     char *name;
0367     __u32 inumber;
0368 
0369     for (i = 0; i < npages; i++) {
0370         char *p, *kaddr, *limit;
0371 
0372         page = dir_get_page(inode, i);
0373         if (IS_ERR(page))
0374             continue;
0375 
0376         kaddr = (char *)page_address(page);
0377         limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize;
0378         for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) {
0379             if (sbi->s_version == MINIX_V3) {
0380                 minix3_dirent *de3 = (minix3_dirent *)p;
0381                 name = de3->name;
0382                 inumber = de3->inode;
0383             } else {
0384                 minix_dirent *de = (minix_dirent *)p;
0385                 name = de->name;
0386                 inumber = de->inode;
0387             }
0388 
0389             if (inumber != 0) {
0390                 /* check for . and .. */
0391                 if (name[0] != '.')
0392                     goto not_empty;
0393                 if (!name[1]) {
0394                     if (inumber != inode->i_ino)
0395                         goto not_empty;
0396                 } else if (name[1] != '.')
0397                     goto not_empty;
0398                 else if (name[2])
0399                     goto not_empty;
0400             }
0401         }
0402         dir_put_page(page);
0403     }
0404     return 1;
0405 
0406 not_empty:
0407     dir_put_page(page);
0408     return 0;
0409 }
0410 
0411 /* Releases the page */
0412 void minix_set_link(struct minix_dir_entry *de, struct page *page,
0413     struct inode *inode)
0414 {
0415     struct inode *dir = page->mapping->host;
0416     struct minix_sb_info *sbi = minix_sb(dir->i_sb);
0417     loff_t pos = page_offset(page) +
0418             (char *)de-(char*)page_address(page);
0419     int err;
0420 
0421     lock_page(page);
0422 
0423     err = minix_prepare_chunk(page, pos, sbi->s_dirsize);
0424     if (err == 0) {
0425         if (sbi->s_version == MINIX_V3)
0426             ((minix3_dirent *) de)->inode = inode->i_ino;
0427         else
0428             de->inode = inode->i_ino;
0429         err = dir_commit_chunk(page, pos, sbi->s_dirsize);
0430     } else {
0431         unlock_page(page);
0432     }
0433     dir_put_page(page);
0434     dir->i_mtime = dir->i_ctime = current_time(dir);
0435     mark_inode_dirty(dir);
0436 }
0437 
0438 struct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)
0439 {
0440     struct page *page = dir_get_page(dir, 0);
0441     struct minix_sb_info *sbi = minix_sb(dir->i_sb);
0442     struct minix_dir_entry *de = NULL;
0443 
0444     if (!IS_ERR(page)) {
0445         de = minix_next_entry(page_address(page), sbi);
0446         *p = page;
0447     }
0448     return de;
0449 }
0450 
0451 ino_t minix_inode_by_name(struct dentry *dentry)
0452 {
0453     struct page *page;
0454     struct minix_dir_entry *de = minix_find_entry(dentry, &page);
0455     ino_t res = 0;
0456 
0457     if (de) {
0458         struct address_space *mapping = page->mapping;
0459         struct inode *inode = mapping->host;
0460         struct minix_sb_info *sbi = minix_sb(inode->i_sb);
0461 
0462         if (sbi->s_version == MINIX_V3)
0463             res = ((minix3_dirent *) de)->inode;
0464         else
0465             res = de->inode;
0466         dir_put_page(page);
0467     }
0468     return res;
0469 }