The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/qnx4/namei.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* 
    2  * QNX4 file system, Linux implementation.
    3  * 
    4  * Version : 0.2.1
    5  * 
    6  * Using parts of the xiafs filesystem.
    7  * 
    8  * History :
    9  * 
   10  * 01-06-1998 by Richard Frowijn : first release.
   11  * 21-06-1998 by Frank Denis : dcache support, fixed error codes.
   12  * 04-07-1998 by Frank Denis : first step for rmdir/unlink.
   13  */
   14 
   15 #include <linux/config.h>
   16 #include <linux/sched.h>
   17 #include <linux/qnx4_fs.h>
   18 #include <linux/kernel.h>
   19 #include <linux/string.h>
   20 #include <linux/stat.h>
   21 #include <linux/fcntl.h>
   22 #include <linux/errno.h>
   23 
   24 #include <asm/segment.h>
   25 
   26 /*
   27  * check if the filename is correct. For some obscure reason, qnx writes a
   28  * new file twice in the directory entry, first with all possible options at 0
   29  * and for a second time the way it is, they want us not to access the qnx
   30  * filesystem when whe are using linux.
   31  */
   32 static int qnx4_match(int len, const char *name,
   33                       struct buffer_head *bh, unsigned long *offset)
   34 {
   35         struct qnx4_inode_entry *de;
   36         int namelen, thislen;
   37 
   38         if (bh == NULL) {
   39                 printk("qnx4: matching unassigned buffer !\n");
   40                 return 0;
   41         }
   42         de = (struct qnx4_inode_entry *) (bh->b_data + *offset);
   43         *offset += QNX4_DIR_ENTRY_SIZE;
   44         if ((de->di_status & QNX4_FILE_LINK) != 0) {
   45                 namelen = QNX4_NAME_MAX;
   46         } else {
   47                 namelen = QNX4_SHORT_NAME_MAX;
   48         }
   49         /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
   50         if (!len && (de->di_fname[0] == '.') && (de->di_fname[1] == '\0')) {
   51                 return 1;
   52         }
   53         thislen = strlen( de->di_fname );
   54         if ( thislen > namelen )
   55                 thislen = namelen;
   56         if (len != thislen) {
   57                 return 0;
   58         }
   59         if (strncmp(name, de->di_fname, len) == 0) {
   60                 if ((de->di_status & (QNX4_FILE_USED|QNX4_FILE_LINK)) != 0) {
   61                         return 1;
   62                 }
   63         }
   64         return 0;
   65 }
   66 
   67 static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
   68            const char *name, struct qnx4_inode_entry **res_dir, int *ino)
   69 {
   70         unsigned long block, offset, blkofs;
   71         struct buffer_head *bh;
   72 
   73         *res_dir = NULL;
   74         if (!dir->i_sb) {
   75                 printk("qnx4: no superblock on dir.\n");
   76                 return NULL;
   77         }
   78         bh = NULL;
   79         block = offset = blkofs = 0;
   80         while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
   81                 if (!bh) {
   82                         bh = qnx4_bread(dir, blkofs, 0);
   83                         if (!bh) {
   84                                 blkofs++;
   85                                 continue;
   86                         }
   87                 }
   88                 *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
   89                 if (qnx4_match(len, name, bh, &offset)) {
   90                         block = qnx4_block_map( dir, blkofs );
   91                         *ino = block * QNX4_INODES_PER_BLOCK +
   92                             (offset / QNX4_DIR_ENTRY_SIZE) - 1;
   93                         return bh;
   94                 }
   95                 if (offset < bh->b_size) {
   96                         continue;
   97                 }
   98                 brelse(bh);
   99                 bh = NULL;
  100                 offset = 0;
  101                 blkofs++;
  102         }
  103         brelse(bh);
  104         *res_dir = NULL;
  105         return NULL;
  106 }
  107 
  108 struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry)
  109 {
  110         int ino;
  111         struct qnx4_inode_entry *de;
  112         struct qnx4_link_info *lnk;
  113         struct buffer_head *bh;
  114         const char *name = dentry->d_name.name;
  115         int len = dentry->d_name.len;
  116         struct inode *foundinode = NULL;
  117 
  118         if (!(bh = qnx4_find_entry(len, dir, name, &de, &ino)))
  119                 goto out;
  120         /* The entry is linked, let's get the real info */
  121         if ((de->di_status & QNX4_FILE_LINK) == QNX4_FILE_LINK) {
  122                 lnk = (struct qnx4_link_info *) de;
  123                 ino = (le32_to_cpu(lnk->dl_inode_blk) - 1) *
  124                     QNX4_INODES_PER_BLOCK +
  125                     lnk->dl_inode_ndx;
  126         }
  127         brelse(bh);
  128 
  129         if ((foundinode = iget(dir->i_sb, ino)) == NULL) {
  130                 QNX4DEBUG(("qnx4: lookup->iget -> NULL\n"));
  131                 return ERR_PTR(-EACCES);
  132         }
  133 out:
  134         d_add(dentry, foundinode);
  135 
  136         return NULL;
  137 }
  138 
  139 #ifdef CONFIG_QNX4FS_RW
  140 int qnx4_create(struct inode *dir, struct dentry *dentry, int mode)
  141 {
  142         QNX4DEBUG(("qnx4: qnx4_create\n"));
  143         if (dir == NULL) {
  144                 return -ENOENT;
  145         }
  146         return -ENOSPC;
  147 }
  148 
  149 int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
  150 {
  151         struct buffer_head *bh;
  152         struct qnx4_inode_entry *de;
  153         struct inode *inode;
  154         int retval;
  155         int ino;
  156 
  157         QNX4DEBUG(("qnx4: qnx4_rmdir [%s]\n", dentry->d_name.name));
  158         bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
  159                              &de, &ino);
  160         if (bh == NULL) {
  161                 return -ENOENT;
  162         }
  163         inode = dentry->d_inode;
  164         if (inode->i_ino != ino) {
  165                 retval = -EIO;
  166                 goto end_rmdir;
  167         }
  168 #if 0
  169         if (!empty_dir(inode)) {
  170                 retval = -ENOTEMPTY;
  171                 goto end_rmdir;
  172         }
  173 #endif
  174         if (inode->i_nlink != 2) {
  175                 QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink));
  176         }
  177         QNX4DEBUG(("qnx4: deleting directory\n"));
  178         de->di_status = 0;
  179         memset(de->di_fname, 0, sizeof de->di_fname);
  180         de->di_mode = 0;
  181         mark_buffer_dirty(bh);
  182         inode->i_nlink = 0;
  183         mark_inode_dirty(inode);
  184         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  185         dir->i_nlink--;
  186         mark_inode_dirty(dir);
  187         retval = 0;
  188 
  189       end_rmdir:
  190         brelse(bh);
  191 
  192         return retval;
  193 }
  194 
  195 int qnx4_unlink(struct inode *dir, struct dentry *dentry)
  196 {
  197         struct buffer_head *bh;
  198         struct qnx4_inode_entry *de;
  199         struct inode *inode;
  200         int retval;
  201         int ino;
  202 
  203         QNX4DEBUG(("qnx4: qnx4_unlink [%s]\n", dentry->d_name.name));
  204         bh = qnx4_find_entry(dentry->d_name.len, dir, dentry->d_name.name,
  205                              &de, &ino);
  206         if (bh == NULL) {
  207                 return -ENOENT;
  208         }
  209         inode = dentry->d_inode;
  210         if (inode->i_ino != ino) {
  211                 retval = -EIO;
  212                 goto end_unlink;
  213         }
  214         retval = -EPERM;
  215         if (!inode->i_nlink) {
  216                 QNX4DEBUG(("Deleting nonexistent file (%s:%lu), %d\n",
  217                            kdevname(inode->i_dev),
  218                            inode->i_ino, inode->i_nlink));
  219                 inode->i_nlink = 1;
  220         }
  221         de->di_status = 0;
  222         memset(de->di_fname, 0, sizeof de->di_fname);
  223         de->di_mode = 0;
  224         mark_buffer_dirty(bh);
  225         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
  226         mark_inode_dirty(dir);
  227         inode->i_nlink--;
  228         inode->i_ctime = dir->i_ctime;
  229         mark_inode_dirty(inode);
  230         retval = 0;
  231 
  232       end_unlink:
  233         brelse(bh);
  234 
  235         return retval;
  236 }
  237 #endif

Cache object: 581e0ec719ea0d9ab50066a42fd4d64c


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.