OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [readdir.c] - Blame information for rev 1627

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1627 jcastillo
/*
2
 *  linux/fs/readdir.c
3
 *
4
 *  Copyright (C) 1995  Linus Torvalds
5
 */
6
 
7
#include <linux/types.h>
8
#include <linux/errno.h>
9
#include <linux/stat.h>
10
#include <linux/kernel.h>
11
#include <linux/sched.h>
12
#include <linux/mm.h>
13
 
14
#include <asm/segment.h>
15
 
16
/*
17
 * Traditional linux readdir() handling..
18
 *
19
 * "count=1" is a special case, meaning that the buffer is one
20
 * dirent-structure in size and that the code can't handle more
21
 * anyway. Thus the special "fillonedir()" function for that
22
 * case (the low-level handlers don't need to care about this).
23
 */
24
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
25
#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
26
 
27
struct old_linux_dirent {
28
        unsigned long   d_ino;
29
        unsigned long   d_offset;
30
        unsigned short  d_namlen;
31
        char            d_name[1];
32
};
33
 
34
struct readdir_callback {
35
        struct old_linux_dirent * dirent;
36
        int count;
37
};
38
 
39
static int fillonedir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
40
{
41
        struct readdir_callback * buf = (struct readdir_callback *) __buf;
42
        struct old_linux_dirent * dirent;
43
 
44
        if (buf->count)
45
                return -EINVAL;
46
        buf->count++;
47
        dirent = buf->dirent;
48
        put_user(ino, &dirent->d_ino);
49
        put_user(offset, &dirent->d_offset);
50
        put_user(namlen, &dirent->d_namlen);
51
        memcpy_tofs(dirent->d_name, name, namlen);
52
        put_user(0, dirent->d_name + namlen);
53
        return 0;
54
}
55
 
56
asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count)
57
{
58
        int error;
59
        struct file * file;
60
        struct readdir_callback buf;
61
 
62
        if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
63
                return -EBADF;
64
        if (!file->f_op || !file->f_op->readdir)
65
                return -ENOTDIR;
66
        error = verify_area(VERIFY_WRITE, dirent, sizeof(struct old_linux_dirent));
67
        if (error)
68
                return error;
69
        buf.count = 0;
70
        buf.dirent = dirent;
71
        error = file->f_op->readdir(file->f_inode, file, &buf, fillonedir);
72
        if (error < 0)
73
                return error;
74
        return buf.count;
75
}
76
 
77
/*
78
 * New, all-improved, singing, dancing, iBCS2-compliant getdents()
79
 * interface.
80
 */
81
struct linux_dirent {
82
        unsigned long   d_ino;
83
        unsigned long   d_off;
84
        unsigned short  d_reclen;
85
        char            d_name[1];
86
};
87
 
88
struct getdents_callback {
89
        struct linux_dirent * current_dir;
90
        struct linux_dirent * previous;
91
        int count;
92
        int error;
93
};
94
 
95
static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
96
{
97
        struct linux_dirent * dirent;
98
        struct getdents_callback * buf = (struct getdents_callback *) __buf;
99
        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
100
 
101
        buf->error = -EINVAL;   /* only used if we fail.. */
102
        if (reclen > buf->count)
103
                return -EINVAL;
104
        dirent = buf->previous;
105
        if (dirent)
106
                put_user(offset, &dirent->d_off);
107
        dirent = buf->current_dir;
108
        buf->previous = dirent;
109
        put_user(ino, &dirent->d_ino);
110
        put_user(reclen, &dirent->d_reclen);
111
        memcpy_tofs(dirent->d_name, name, namlen);
112
        put_user(0, dirent->d_name + namlen);
113
        ((char *) dirent) += reclen;
114
        buf->current_dir = dirent;
115
        buf->count -= reclen;
116
        return 0;
117
}
118
 
119
asmlinkage int sys_getdents(unsigned int fd, void * dirent, unsigned int count)
120
{
121
        struct file * file;
122
        struct linux_dirent * lastdirent;
123
        struct getdents_callback buf;
124
        int error;
125
 
126
        if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
127
                return -EBADF;
128
        if (!file->f_op || !file->f_op->readdir)
129
                return -ENOTDIR;
130
        error = verify_area(VERIFY_WRITE, dirent, count);
131
        if (error)
132
                return error;
133
        buf.current_dir = (struct linux_dirent *) dirent;
134
        buf.previous = NULL;
135
        buf.count = count;
136
        buf.error = 0;
137
        error = file->f_op->readdir(file->f_inode, file, &buf, filldir);
138
        if (error < 0)
139
                return error;
140
        lastdirent = buf.previous;
141
        if (!lastdirent)
142
                return buf.error;
143
        put_user(file->f_pos, &lastdirent->d_off);
144
        return count - buf.count;
145
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.