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/ufs/dir.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  *  linux/fs/ufs/ufs_dir.c
    3  *
    4  * Copyright (C) 1996
    5  * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
    6  * Laboratory for Computer Science Research Computing Facility
    7  * Rutgers, The State University of New Jersey
    8  *
    9  * swab support by Francois-Rene Rideau <fare@tunes.org> 19970406
   10  *
   11  * 4.4BSD (FreeBSD) support added on February 1st 1998 by
   12  * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
   13  * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
   14  */
   15 
   16 #include <linux/sched.h>
   17 #include <linux/locks.h>
   18 #include <linux/fs.h>
   19 #include <linux/ufs_fs.h>
   20 
   21 #include "swab.h"
   22 #include "util.h"
   23 
   24 #undef UFS_DIR_DEBUG
   25 
   26 #ifdef UFS_DIR_DEBUG
   27 #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
   28 #else
   29 #define UFSD(x)
   30 #endif
   31 
   32 
   33 
   34 /*
   35  * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
   36  *
   37  * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
   38  */
   39 static inline int ufs_match(struct super_block *sb, int len,
   40                 const char * const name, struct ufs_dir_entry * de)
   41 {
   42         if (len != ufs_get_de_namlen(sb, de))
   43                 return 0;
   44         if (!de->d_ino)
   45                 return 0;
   46         return !memcmp(name, de->d_name, len);
   47 }
   48 
   49 /*
   50  * This is blatantly stolen from ext2fs
   51  */
   52 static int
   53 ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
   54 {
   55         struct inode *inode = filp->f_dentry->d_inode;
   56         int error = 0;
   57         unsigned long offset, lblk, blk;
   58         int i, stored;
   59         struct buffer_head * bh;
   60         struct ufs_dir_entry * de;
   61         struct super_block * sb;
   62         int de_reclen;
   63         unsigned flags;
   64 
   65         sb = inode->i_sb;
   66         flags = sb->u.ufs_sb.s_flags;
   67 
   68         UFSD(("ENTER, ino %lu  f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos))
   69 
   70         stored = 0;
   71         bh = NULL;
   72         offset = filp->f_pos & (sb->s_blocksize - 1);
   73 
   74         while (!error && !stored && filp->f_pos < inode->i_size) {
   75                 lblk = (filp->f_pos) >> sb->s_blocksize_bits;
   76                 blk = ufs_frag_map(inode, lblk);
   77                 if (!blk || !(bh = sb_bread(sb, blk))) {
   78                         /* XXX - error - skip to the next block */
   79                         printk("ufs_readdir: "
   80                                "dir inode %lu has a hole at offset %lu\n",
   81                                inode->i_ino, (unsigned long int)filp->f_pos);
   82                         filp->f_pos += sb->s_blocksize - offset;
   83                         continue;
   84                 }
   85 
   86 revalidate:
   87                 /* If the dir block has changed since the last call to
   88                  * readdir(2), then we might be pointing to an invalid
   89                  * dirent right now.  Scan from the start of the block
   90                  * to make sure. */
   91                 if (filp->f_version != inode->i_version) {
   92                         for (i = 0; i < sb->s_blocksize && i < offset; ) {
   93                                 de = (struct ufs_dir_entry *)(bh->b_data + i);
   94                                 /* It's too expensive to do a full
   95                                  * dirent test each time round this
   96                                  * loop, but we do have to test at
   97                                  * least that it is non-zero.  A
   98                                  * failure will be detected in the
   99                                  * dirent test below. */
  100                                 de_reclen = fs16_to_cpu(sb, de->d_reclen);
  101                                 if (de_reclen < 1)
  102                                         break;
  103                                 i += de_reclen;
  104                         }
  105                         offset = i;
  106                         filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
  107                                 | offset;
  108                         filp->f_version = inode->i_version;
  109                 }
  110 
  111                 while (!error && filp->f_pos < inode->i_size
  112                        && offset < sb->s_blocksize) {
  113                         de = (struct ufs_dir_entry *) (bh->b_data + offset);
  114                         /* XXX - put in a real ufs_check_dir_entry() */
  115                         if ((de->d_reclen == 0) || (ufs_get_de_namlen(sb, de) == 0)) {
  116                                 filp->f_pos = (filp->f_pos &
  117                                               (sb->s_blocksize - 1)) +
  118                                                sb->s_blocksize;
  119                                 brelse(bh);
  120                                 return stored;
  121                         }
  122                         if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
  123                                                    bh, offset)) {
  124                                 /* On error, skip the f_pos to the
  125                                    next block. */
  126                                 filp->f_pos = (filp->f_pos |
  127                                               (sb->s_blocksize - 1)) +
  128                                                1;
  129                                 brelse (bh);
  130                                 return stored;
  131                         }
  132                         offset += fs16_to_cpu(sb, de->d_reclen);
  133                         if (de->d_ino) {
  134                                 /* We might block in the next section
  135                                  * if the data destination is
  136                                  * currently swapped out.  So, use a
  137                                  * version stamp to detect whether or
  138                                  * not the directory has been modified
  139                                  * during the copy operation. */
  140                                 unsigned long version = filp->f_version;
  141                                 unsigned char d_type = DT_UNKNOWN;
  142 
  143                                 UFSD(("filldir(%s,%u)\n", de->d_name,
  144                                                         fs32_to_cpu(sb, de->d_ino)))
  145                                 UFSD(("namlen %u\n", ufs_get_de_namlen(sb, de)))
  146 
  147                                 if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
  148                                         d_type = de->d_u.d_44.d_type;
  149                                 error = filldir(dirent, de->d_name,
  150                                                 ufs_get_de_namlen(sb, de), filp->f_pos,
  151                                                 fs32_to_cpu(sb, de->d_ino), d_type);
  152                                 if (error)
  153                                         break;
  154                                 if (version != filp->f_version)
  155                                         goto revalidate;
  156                                 stored ++;
  157                         }
  158                         filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
  159                 }
  160                 offset = 0;
  161                 brelse (bh);
  162         }
  163         UPDATE_ATIME(inode);
  164         return 0;
  165 }
  166 
  167 /*
  168  * define how far ahead to read directories while searching them.
  169  */
  170 #define NAMEI_RA_CHUNKS  2
  171 #define NAMEI_RA_BLOCKS  4
  172 #define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
  173 #define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
  174 
  175 /*
  176  *      ufs_find_entry()
  177  *
  178  * finds an entry in the specified directory with the wanted name. It
  179  * returns the cache buffer in which the entry was found, and the entry
  180  * itself (as a parameter - res_bh). It does NOT read the inode of the
  181  * entry - you'll have to do that yourself if you want to.
  182  */
  183 struct ufs_dir_entry * ufs_find_entry (struct dentry *dentry,
  184         struct buffer_head ** res_bh)
  185 {
  186         struct super_block * sb;
  187         struct buffer_head * bh_use[NAMEI_RA_SIZE];
  188         struct buffer_head * bh_read[NAMEI_RA_SIZE];
  189         unsigned long offset;
  190         int block, toread, i, err;
  191         struct inode *dir = dentry->d_parent->d_inode;
  192         const char *name = dentry->d_name.name;
  193         int namelen = dentry->d_name.len;
  194 
  195         UFSD(("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen))
  196         
  197         *res_bh = NULL;
  198         
  199         sb = dir->i_sb;
  200         
  201         if (namelen > UFS_MAXNAMLEN)
  202                 return NULL;
  203 
  204         memset (bh_use, 0, sizeof (bh_use));
  205         toread = 0;
  206         for (block = 0; block < NAMEI_RA_SIZE; ++block) {
  207                 struct buffer_head * bh;
  208 
  209                 if ((block << sb->s_blocksize_bits) >= dir->i_size)
  210                         break;
  211                 bh = ufs_getfrag (dir, block, 0, &err);
  212                 bh_use[block] = bh;
  213                 if (bh && !buffer_uptodate(bh))
  214                         bh_read[toread++] = bh;
  215         }
  216 
  217         for (block = 0, offset = 0; offset < dir->i_size; block++) {
  218                 struct buffer_head * bh;
  219                 struct ufs_dir_entry * de;
  220                 char * dlimit;
  221 
  222                 if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
  223                         ll_rw_block (READ, toread, bh_read);
  224                         toread = 0;
  225                 }
  226                 bh = bh_use[block % NAMEI_RA_SIZE];
  227                 if (!bh) {
  228                         ufs_error (sb, "ufs_find_entry", 
  229                                 "directory #%lu contains a hole at offset %lu",
  230                                 dir->i_ino, offset);
  231                         offset += sb->s_blocksize;
  232                         continue;
  233                 }
  234                 wait_on_buffer (bh);
  235                 if (!buffer_uptodate(bh)) {
  236                         /*
  237                          * read error: all bets are off
  238                          */
  239                         break;
  240                 }
  241 
  242                 de = (struct ufs_dir_entry *) bh->b_data;
  243                 dlimit = bh->b_data + sb->s_blocksize;
  244                 while ((char *) de < dlimit && offset < dir->i_size) {
  245                         /* this code is executed quadratically often */
  246                         /* do minimal checking by hand */
  247                         int de_len;
  248 
  249                         if ((char *) de + namelen <= dlimit &&
  250                             ufs_match(sb, namelen, name, de)) {
  251                                 /* found a match -
  252                                 just to be sure, do a full check */
  253                                 if (!ufs_check_dir_entry("ufs_find_entry",
  254                                     dir, de, bh, offset))
  255                                         goto failed;
  256                                 for (i = 0; i < NAMEI_RA_SIZE; ++i) {
  257                                         if (bh_use[i] != bh)
  258                                                 brelse (bh_use[i]);
  259                                 }
  260                                 *res_bh = bh;
  261                                 return de;
  262                         }
  263                         /* prevent looping on a bad block */
  264                         de_len = fs16_to_cpu(sb, de->d_reclen);
  265                         if (de_len <= 0)
  266                                 goto failed;
  267                         offset += de_len;
  268                         de = (struct ufs_dir_entry *) ((char *) de + de_len);
  269                 }
  270 
  271                 brelse (bh);
  272                 if (((block + NAMEI_RA_SIZE) << sb->s_blocksize_bits ) >=
  273                     dir->i_size)
  274                         bh = NULL;
  275                 else
  276                         bh = ufs_getfrag (dir, block + NAMEI_RA_SIZE, 0, &err);
  277                 bh_use[block % NAMEI_RA_SIZE] = bh;
  278                 if (bh && !buffer_uptodate(bh))
  279                         bh_read[toread++] = bh;
  280         }
  281 
  282 failed:
  283         for (i = 0; i < NAMEI_RA_SIZE; ++i) brelse (bh_use[i]);
  284         UFSD(("EXIT\n"))
  285         return NULL;
  286 }
  287 
  288 int ufs_check_dir_entry (const char * function, struct inode * dir,
  289         struct ufs_dir_entry * de, struct buffer_head * bh, 
  290         unsigned long offset)
  291 {
  292         struct super_block *sb = dir->i_sb;
  293         const char *error_msg = NULL;
  294         int rlen = fs16_to_cpu(sb, de->d_reclen);
  295 
  296         if (rlen < UFS_DIR_REC_LEN(1))
  297                 error_msg = "reclen is smaller than minimal";
  298         else if (rlen % 4 != 0)
  299                 error_msg = "reclen % 4 != 0";
  300         else if (rlen < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)))
  301                 error_msg = "reclen is too small for namlen";
  302         else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
  303                 error_msg = "directory entry across blocks";
  304         else if (fs32_to_cpu(sb, de->d_ino) > (sb->u.ufs_sb.s_uspi->s_ipg *
  305                                       sb->u.ufs_sb.s_uspi->s_ncg))
  306                 error_msg = "inode out of bounds";
  307 
  308         if (error_msg != NULL)
  309                 ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
  310                             "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
  311                             dir->i_ino, dir->i_size, error_msg, offset,
  312                             (unsigned long)fs32_to_cpu(sb, de->d_ino),
  313                             rlen, ufs_get_de_namlen(sb, de));
  314         
  315         return (error_msg == NULL ? 1 : 0);
  316 }
  317 
  318 struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct buffer_head **p)
  319 {
  320         int err;
  321         struct buffer_head *bh = ufs_bread (dir, 0, 0, &err);
  322         struct ufs_dir_entry *res = NULL;
  323 
  324         if (bh) {
  325                 res = (struct ufs_dir_entry *) bh->b_data;
  326                 res = (struct ufs_dir_entry *)((char *)res +
  327                         fs16_to_cpu(dir->i_sb, res->d_reclen));
  328         }
  329         *p = bh;
  330         return res;
  331 }
  332 ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry)
  333 {
  334         ino_t res = 0;
  335         struct ufs_dir_entry * de;
  336         struct buffer_head *bh;
  337 
  338         de = ufs_find_entry (dentry, &bh);
  339         if (de) {
  340                 res = fs32_to_cpu(dir->i_sb, de->d_ino);
  341                 brelse(bh);
  342         }
  343         return res;
  344 }
  345 
  346 void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
  347                 struct buffer_head *bh, struct inode *inode)
  348 {
  349         dir->i_version = ++event;
  350         de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
  351         mark_buffer_dirty(bh);
  352         if (IS_SYNC(dir)) {
  353                 ll_rw_block (WRITE, 1, &bh);
  354                 wait_on_buffer(bh);
  355         }
  356         brelse (bh);
  357 }
  358 
  359 /*
  360  *      ufs_add_entry()
  361  *
  362  * adds a file entry to the specified directory, using the same
  363  * semantics as ufs_find_entry(). It returns NULL if it failed.
  364  */
  365 int ufs_add_link(struct dentry *dentry, struct inode *inode)
  366 {
  367         struct super_block * sb;
  368         struct ufs_sb_private_info * uspi;
  369         unsigned long offset;
  370         unsigned fragoff;
  371         unsigned short rec_len;
  372         struct buffer_head * bh;
  373         struct ufs_dir_entry * de, * de1;
  374         struct inode *dir = dentry->d_parent->d_inode;
  375         const char *name = dentry->d_name.name;
  376         int namelen = dentry->d_name.len;
  377         int err;
  378 
  379         UFSD(("ENTER, name %s, namelen %u\n", name, namelen))
  380         
  381         sb = dir->i_sb;
  382         uspi = sb->u.ufs_sb.s_uspi;
  383 
  384         if (!namelen)
  385                 return -EINVAL;
  386         bh = ufs_bread (dir, 0, 0, &err);
  387         if (!bh)
  388                 return err;
  389         rec_len = UFS_DIR_REC_LEN(namelen);
  390         offset = 0;
  391         de = (struct ufs_dir_entry *) bh->b_data;
  392         while (1) {
  393                 if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) {
  394                         fragoff = offset & ~uspi->s_fmask;
  395                         if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE)
  396                                 ufs_error (sb, "ufs_add_entry", "internal error"
  397                                         " fragoff %u", fragoff);
  398                         if (!fragoff) {
  399                                 brelse (bh);
  400                                 bh = ufs_bread (dir, offset >> sb->s_blocksize_bits, 1, &err);
  401                                 if (!bh)
  402                                         return err;
  403                         }
  404                         if (dir->i_size <= offset) {
  405                                 if (dir->i_size == 0) {
  406                                         brelse(bh);
  407                                         return -ENOENT;
  408                                 }
  409                                 de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
  410                                 de->d_ino = 0;
  411                                 de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
  412                                 ufs_set_de_namlen(sb, de, 0);
  413                                 dir->i_size = offset + UFS_SECTOR_SIZE;
  414                                 mark_inode_dirty(dir);
  415                         } else {
  416                                 de = (struct ufs_dir_entry *) bh->b_data;
  417                         }
  418                 }
  419                 if (!ufs_check_dir_entry ("ufs_add_entry", dir, de, bh, offset)) {
  420                         brelse (bh);
  421                         return -ENOENT;
  422                 }
  423                 if (ufs_match(sb, namelen, name, de)) {
  424                         brelse (bh);
  425                         return -EEXIST;
  426                 }
  427                 if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len)
  428                         break;
  429                         
  430                 if (fs16_to_cpu(sb, de->d_reclen) >=
  431                      UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len)
  432                         break;
  433                 offset += fs16_to_cpu(sb, de->d_reclen);
  434                 de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen));
  435         }
  436 
  437         if (de->d_ino) {
  438                 de1 = (struct ufs_dir_entry *) ((char *) de +
  439                         UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  440                 de1->d_reclen =
  441                         cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) -
  442                                 UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  443                 de->d_reclen =
  444                         cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  445                 de = de1;
  446         }
  447         de->d_ino = 0;
  448         ufs_set_de_namlen(sb, de, namelen);
  449         memcpy (de->d_name, name, namelen + 1);
  450         de->d_ino = cpu_to_fs32(sb, inode->i_ino);
  451         ufs_set_de_type(sb, de, inode->i_mode);
  452         mark_buffer_dirty(bh);
  453         if (IS_SYNC(dir)) {
  454                 ll_rw_block (WRITE, 1, &bh);
  455                 wait_on_buffer (bh);
  456         }
  457         brelse (bh);
  458         dir->i_mtime = dir->i_ctime = CURRENT_TIME;
  459         dir->i_version = ++event;
  460         mark_inode_dirty(dir);
  461 
  462         UFSD(("EXIT\n"))
  463         return 0;
  464 }
  465 
  466 /*
  467  * ufs_delete_entry deletes a directory entry by merging it with the
  468  * previous entry.
  469  */
  470 int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
  471         struct buffer_head * bh )
  472         
  473 {
  474         struct super_block * sb;
  475         struct ufs_dir_entry * de, * pde;
  476         unsigned i;
  477         
  478         UFSD(("ENTER\n"))
  479 
  480         sb = inode->i_sb;
  481         i = 0;
  482         pde = NULL;
  483         de = (struct ufs_dir_entry *) bh->b_data;
  484         
  485         UFSD(("ino %u, reclen %u, namlen %u, name %s\n",
  486                 fs32_to_cpu(sb, de->d_ino),
  487                 fs16to_cpu(sb, de->d_reclen),
  488                 ufs_get_de_namlen(sb, de), de->d_name))
  489 
  490         while (i < bh->b_size) {
  491                 if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) {
  492                         brelse(bh);
  493                         return -EIO;
  494                 }
  495                 if (de == dir)  {
  496                         if (pde)
  497                                 fs16_add(sb, &pde->d_reclen,
  498                                         fs16_to_cpu(sb, dir->d_reclen));
  499                         dir->d_ino = 0;
  500                         inode->i_version = ++event;
  501                         inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  502                         mark_inode_dirty(inode);
  503                         mark_buffer_dirty(bh);
  504                         if (IS_SYNC(inode)) {
  505                                 ll_rw_block(WRITE, 1, &bh);
  506                                 wait_on_buffer(bh);
  507                         }
  508                         brelse(bh);
  509                         UFSD(("EXIT\n"))
  510                         return 0;
  511                 }
  512                 i += fs16_to_cpu(sb, de->d_reclen);
  513                 if (i == UFS_SECTOR_SIZE) pde = NULL;
  514                 else pde = de;
  515                 de = (struct ufs_dir_entry *)
  516                     ((char *) de + fs16_to_cpu(sb, de->d_reclen));
  517                 if (i == UFS_SECTOR_SIZE && de->d_reclen == 0)
  518                         break;
  519         }
  520         UFSD(("EXIT\n"))
  521         brelse(bh);
  522         return -ENOENT;
  523 }
  524 
  525 int ufs_make_empty(struct inode * inode, struct inode *dir)
  526 {
  527         struct super_block * sb = dir->i_sb;
  528         struct buffer_head * dir_block;
  529         struct ufs_dir_entry * de;
  530         int err;
  531 
  532         dir_block = ufs_bread (inode, 0, 1, &err);
  533         if (!dir_block)
  534                 return err;
  535 
  536         inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
  537         de = (struct ufs_dir_entry *) dir_block->b_data;
  538         de->d_ino = cpu_to_fs32(sb, inode->i_ino);
  539         ufs_set_de_type(sb, de, inode->i_mode);
  540         ufs_set_de_namlen(sb, de, 1);
  541         de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1));
  542         strcpy (de->d_name, ".");
  543         de = (struct ufs_dir_entry *)
  544                 ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  545         de->d_ino = cpu_to_fs32(sb, dir->i_ino);
  546         ufs_set_de_type(sb, de, dir->i_mode);
  547         de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
  548         ufs_set_de_namlen(sb, de, 2);
  549         strcpy (de->d_name, "..");
  550         mark_buffer_dirty(dir_block);
  551         brelse (dir_block);
  552         mark_inode_dirty(inode);
  553         return 0;
  554 }
  555 
  556 /*
  557  * routine to check that the specified directory is empty (for rmdir)
  558  */
  559 int ufs_empty_dir (struct inode * inode)
  560 {
  561         struct super_block * sb;
  562         unsigned long offset;
  563         struct buffer_head * bh;
  564         struct ufs_dir_entry * de, * de1;
  565         int err;
  566         
  567         sb = inode->i_sb;
  568 
  569         if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
  570             !(bh = ufs_bread (inode, 0, 0, &err))) {
  571                 ufs_warning (inode->i_sb, "empty_dir",
  572                               "bad directory (dir #%lu) - no data block",
  573                               inode->i_ino);
  574                 return 1;
  575         }
  576         de = (struct ufs_dir_entry *) bh->b_data;
  577         de1 = (struct ufs_dir_entry *)
  578                 ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  579         if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 ||
  580              strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
  581                 ufs_warning (inode->i_sb, "empty_dir",
  582                               "bad directory (dir #%lu) - no `.' or `..'",
  583                               inode->i_ino);
  584                 return 1;
  585         }
  586         offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen);
  587         de = (struct ufs_dir_entry *)
  588                 ((char *)de1 + fs16_to_cpu(sb, de1->d_reclen));
  589         while (offset < inode->i_size ) {
  590                 if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
  591                         brelse (bh);
  592                         bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);
  593                         if (!bh) {
  594                                 ufs_error (sb, "empty_dir",
  595                                             "directory #%lu contains a hole at offset %lu",
  596                                             inode->i_ino, offset);
  597                                 offset += sb->s_blocksize;
  598                                 continue;
  599                         }
  600                         de = (struct ufs_dir_entry *) bh->b_data;
  601                 }
  602                 if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) {
  603                         brelse (bh);
  604                         return 1;
  605                 }
  606                 if (de->d_ino) {
  607                         brelse (bh);
  608                         return 0;
  609                 }
  610                 offset += fs16_to_cpu(sb, de->d_reclen);
  611                 de = (struct ufs_dir_entry *)
  612                         ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  613         }
  614         brelse (bh);
  615         return 1;
  616 }
  617 
  618 struct file_operations ufs_dir_operations = {
  619         read:           generic_read_dir,
  620         readdir:        ufs_readdir,
  621         fsync:          file_fsync,
  622 };

Cache object: 1adfa3e5afc9e8f2244d951280f7f1ce


[ 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.