home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / fs / ext2 / dir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  3.9 KB  |  152 lines

  1. /*
  2.  *  linux/fs/ext2/dir.c
  3.  *
  4.  *  Copyright (C) 1992, 1993  Remy Card (card@masi.ibp.fr)
  5.  *
  6.  *  from
  7.  *
  8.  *  linux/fs/minix/dir.c
  9.  *
  10.  *  Copyright (C) 1991, 1992  Linus Torvalds
  11.  *
  12.  *  ext2 directory handling functions
  13.  */
  14.  
  15. #include <asm/segment.h>
  16.  
  17. #include <linux/errno.h>
  18. #include <linux/fs.h>
  19. #include <linux/ext2_fs.h>
  20. #include <linux/sched.h>
  21. #include <linux/stat.h>
  22.  
  23. #if 0
  24. static int ext2_dir_read (struct inode * inode, struct file * filp,
  25.                 char * buf, int count)
  26. {
  27.     return -EISDIR;
  28. }
  29. #endif
  30.  
  31. /* static */ int ext2_file_read (struct inode *, struct file *, char *, int);
  32. static int ext2_readdir (struct inode *, struct file *, struct dirent *, int);
  33.  
  34. static struct file_operations ext2_dir_operations = {
  35.     NULL,            /* lseek - default */
  36.     ext2_file_read,        /* read */
  37.     NULL,            /* write - bad */
  38.     ext2_readdir,        /* readdir */
  39.     NULL,            /* select - default */
  40.     ext2_ioctl,        /* ioctl */
  41.     NULL,            /* mmap */
  42.     NULL,            /* no special open code */
  43.     NULL,            /* no special release code */
  44.     file_fsync        /* fsync */
  45. };
  46.  
  47. /*
  48.  * directories can handle most operations...
  49.  */
  50. struct inode_operations ext2_dir_inode_operations = {
  51.     &ext2_dir_operations,    /* default directory file-ops */
  52.     ext2_create,        /* create */
  53.     ext2_lookup,        /* lookup */
  54.     ext2_link,        /* link */
  55.     ext2_unlink,        /* unlink */
  56.     ext2_symlink,        /* symlink */
  57.     ext2_mkdir,        /* mkdir */
  58.     ext2_rmdir,        /* rmdir */
  59.     ext2_mknod,        /* mknod */
  60.     ext2_rename,        /* rename */
  61.     NULL,            /* readlink */
  62.     NULL,            /* follow_link */
  63.     NULL,            /* bmap */
  64.     ext2_truncate,        /* truncate */
  65.     ext2_permission        /* permission */
  66. };
  67.  
  68. int ext2_check_dir_entry (char * function, struct inode * dir,
  69.               struct ext2_dir_entry * de, struct buffer_head * bh,
  70.               unsigned long offset)
  71. {
  72.     char * error_msg = NULL;
  73.  
  74.     if (de->rec_len < EXT2_DIR_REC_LEN(1))
  75.         error_msg = "rec_len is smaller than minimal";
  76.     else if (de->rec_len % 4 != 0)
  77.         error_msg = "rec_len % 4 != 0";
  78.     else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len))
  79.         error_msg = "rec_len is too small for name_len";
  80.     else if (dir && ((char *) de - bh->b_data) + de->rec_len >
  81.          dir->i_sb->s_blocksize)
  82.         error_msg = "directory entry across blocks";
  83.  
  84.     if (error_msg != NULL)
  85.         ext2_error (dir->i_sb, function, "bad directory entry: %s\n"
  86.                 "offset=%lu, inode=%lu, rec_len=%d, name_len=%d",
  87.                 error_msg, offset, de->inode, de->rec_len,
  88.                 de->name_len);
  89.     return error_msg == NULL ? 1 : 0;
  90. }
  91.  
  92. static int ext2_readdir (struct inode * inode, struct file * filp,
  93.              struct dirent * dirent, int count)
  94. {
  95.     unsigned long offset;
  96.     int i;
  97.     struct buffer_head * bh;
  98.     struct ext2_dir_entry * de;
  99.     struct super_block * sb;
  100.     int err;
  101.     
  102.     if (!inode || !S_ISDIR(inode->i_mode))
  103.         return -EBADF;
  104.     sb = inode->i_sb;
  105.     while (filp->f_pos < inode->i_size) {
  106.         offset = filp->f_pos & (sb->s_blocksize - 1);
  107.         bh = ext2_bread (inode, (filp->f_pos) >> EXT2_BLOCK_SIZE_BITS(sb),
  108.                  0, &err);
  109.         if (!bh) {
  110.             filp->f_pos += sb->s_blocksize - offset;
  111.             continue;
  112.         }
  113.         de = (struct ext2_dir_entry *) (offset + bh->b_data);
  114.         while (offset < sb->s_blocksize && filp->f_pos < inode->i_size) {
  115.             if (! ext2_check_dir_entry ("ext2_readdir", inode, de,
  116.                             bh, offset)) {
  117.                 brelse (bh);
  118.                 return 0;
  119.             }
  120.             offset += de->rec_len;
  121.             filp->f_pos += de->rec_len;
  122.             if (de->inode) {
  123.                 memcpy_tofs (dirent->d_name, de->name,
  124.                          de->name_len);
  125.                 put_fs_long (de->inode, &dirent->d_ino);
  126.                 put_fs_byte (0, de->name_len + dirent->d_name);
  127.                 put_fs_word (de->name_len, &dirent->d_reclen);
  128. #ifndef DONT_USE_DCACHE
  129.                 ext2_dcache_add (inode->i_dev, inode->i_ino,
  130.                          de->name, de->name_len,
  131.                          de->inode);
  132. #endif
  133.                 i = de->name_len;
  134.                 brelse (bh);
  135.                 if (!IS_RDONLY(inode)) {
  136.                     inode->i_atime = CURRENT_TIME;
  137.                     inode->i_dirt = 1;
  138.                 }
  139.                 return i;
  140.             }
  141.             de = (struct ext2_dir_entry *) ((char *) de +
  142.                             de->rec_len);
  143.         }
  144.         brelse (bh);
  145.     }
  146.     if (!IS_RDONLY(inode)) {
  147.         inode->i_atime = CURRENT_TIME;
  148.         inode->i_dirt = 1;
  149.     }
  150.     return 0;
  151. }
  152.