File: dir.c

package info (click to toggle)
kernel-source-2.0.35 2.0.35-3
  • links: PTS
  • area: main
  • in suites: slink
  • size: 32,456 kB
  • ctags: 94,327
  • sloc: ansic: 587,014; asm: 26,388; makefile: 4,055; sh: 1,221; perl: 727; tcl: 408; cpp: 277; lisp: 211; awk: 134
file content (131 lines) | stat: -rw-r--r-- 3,657 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 *  linux/fs/xiafs/dir.c
 *  
 *  Copyright (C) Q. Frank Xia, 1993.
 *  
 *  Based on Linus' minix/dir.c
 *  Copyright (C) Linus Torvalds, 1991, 1992.
 *
 *  This software may be redistributed per Linux Copyright.
 */

#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/xia_fs.h>
#include <linux/stat.h>

#include <asm/segment.h>

#include "xiafs_mac.h"

static int xiafs_dir_read(struct inode *, struct file *, char *, int);
static int xiafs_readdir(struct inode *, struct file *, void *, filldir_t);

static struct file_operations xiafs_dir_operations = {
    NULL,		/* lseek - default */
    xiafs_dir_read,	/* read */
    NULL,		/* write - bad */
    xiafs_readdir,	/* readdir */
    NULL,		/* select - default */
    NULL,		/* ioctl - default */
    NULL,		/* mmap */
    NULL,		/* no special open code */
    NULL,		/* no special release code */
    file_fsync		/* default fsync */
};

/*
 * directories can handle most operations...
 */
struct inode_operations xiafs_dir_inode_operations = {
    &xiafs_dir_operations,	/* default directory file-ops */
    xiafs_create,			/* create */
    xiafs_lookup,			/* lookup */
    xiafs_link,			/* link */
    xiafs_unlink,			/* unlink */
    xiafs_symlink,		/* symlink */
    xiafs_mkdir,			/* mkdir */
    xiafs_rmdir,			/* rmdir */
    xiafs_mknod,			/* mknod */
    xiafs_rename,			/* rename */
    NULL,			/* readlink */
    NULL,			/* follow_link */
    NULL,			/* readpage */
    NULL,			/* writepage */
    NULL,			/* bmap */
    xiafs_truncate,		/* truncate */
    NULL			/* permission */
};

static int xiafs_dir_read(struct inode * inode, 
			struct file * filp, char * buf, int count)
{
  return -EISDIR;
}

static int xiafs_readdir(struct inode * inode, struct file * filp,
	void * dirent, filldir_t filldir)
{
    u_int offset, i;
    struct buffer_head * bh;
    struct xiafs_direct * de;

    if (!inode || !inode->i_sb || !S_ISDIR(inode->i_mode))
        return -EBADF;
    if (inode->i_size & (XIAFS_ZSIZE(inode->i_sb) - 1) )
        return -EBADF;
    while (filp->f_pos < inode->i_size) {
        offset = filp->f_pos & (XIAFS_ZSIZE(inode->i_sb) - 1);
	bh = xiafs_bread(inode, filp->f_pos >> XIAFS_ZSIZE_BITS(inode->i_sb),0);
	if (!bh) {
	    filp->f_pos += XIAFS_ZSIZE(inode->i_sb)-offset;
	    continue;
	}
	for (i = 0; i < XIAFS_ZSIZE(inode->i_sb) && i < offset; ) {
	    de = (struct xiafs_direct *) (bh->b_data + i);
	    if (!de->d_rec_len)
		break;
	    i += de->d_rec_len;
	}
	offset = i;
	de = (struct xiafs_direct *) (offset + bh->b_data);
	
	while (offset < XIAFS_ZSIZE(inode->i_sb) && filp->f_pos < inode->i_size) {
	    if (de->d_ino > inode->i_sb->u.xiafs_sb.s_ninodes ||
		de->d_rec_len < 12 || 
		(char *)de+de->d_rec_len > XIAFS_ZSIZE(inode->i_sb)+bh->b_data ||
		de->d_name_len < 1 || de->d_name_len + 8 > de->d_rec_len ||
		de->d_name_len > _XIAFS_NAME_LEN ||
		de->d_name[de->d_name_len] ) {
	        printk("XIA-FS: bad directory entry (%s %d)\n", WHERE_ERR);
		brelse(bh);
		return 0;
	    }  
	    if (de->d_ino) {
		if (!IS_RDONLY (inode)) {
		    inode->i_atime=CURRENT_TIME;
		    inode->i_dirt=1;
		}
		if (filldir(dirent, de->d_name, de->d_name_len, filp->f_pos, de->d_ino) < 0) {
		    brelse(bh);
		    return 0;
		}
	    }
	    offset += de->d_rec_len;
	    filp->f_pos += de->d_rec_len;
	    de = (struct xiafs_direct *) (offset + bh->b_data);
	}
	brelse(bh);
	if (offset > XIAFS_ZSIZE(inode->i_sb)) {
	    printk("XIA-FS: bad directory (%s %d)\n", WHERE_ERR);
	    return 0;
	}
    }
    if (!IS_RDONLY (inode)) {
	inode->i_atime=CURRENT_TIME;		    
	inode->i_dirt=1;
    }
    return 0;
}