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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [ncpfs/] [file.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  file.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Volker Lendecke
5
 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
6
 *
7
 */
8
 
9
#include <asm/uaccess.h>
10
#include <asm/system.h>
11
 
12
#include <linux/sched.h>
13
#include <linux/kernel.h>
14
#include <linux/errno.h>
15
#include <linux/fcntl.h>
16
#include <linux/stat.h>
17
#include <linux/mm.h>
18
#include <linux/locks.h>
19
#include <linux/slab.h>
20
#include <linux/vmalloc.h>
21
 
22
#include <linux/ncp_fs.h>
23
#include "ncplib_kernel.h"
24
 
25
static int ncp_fsync(struct file *file, struct dentry *dentry, int datasync)
26
{
27
        return 0;
28
}
29
 
30
/*
31
 * Open a file with the specified read/write mode.
32
 */
33
int ncp_make_open(struct inode *inode, int right)
34
{
35
        int error;
36
        int access;
37
 
38
        error = -EINVAL;
39
        if (!inode) {
40
                printk(KERN_ERR "ncp_make_open: got NULL inode\n");
41
                goto out;
42
        }
43
 
44
        DPRINTK("ncp_make_open: opened=%d, volume # %u, dir entry # %u\n",
45
                atomic_read(&NCP_FINFO(inode)->opened),
46
                NCP_FINFO(inode)->volNumber,
47
                NCP_FINFO(inode)->dirEntNum);
48
        error = -EACCES;
49
        down(&NCP_FINFO(inode)->open_sem);
50
        if (!atomic_read(&NCP_FINFO(inode)->opened)) {
51
                struct ncp_entry_info finfo;
52
                int result;
53
 
54
                finfo.i.dirEntNum = NCP_FINFO(inode)->dirEntNum;
55
                finfo.i.volNumber = NCP_FINFO(inode)->volNumber;
56
                /* tries max. rights */
57
                finfo.access = O_RDWR;
58
                result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
59
                                        NULL, NULL, OC_MODE_OPEN,
60
                                        0, AR_READ | AR_WRITE, &finfo);
61
                if (!result)
62
                        goto update;
63
                /* RDWR did not succeeded, try readonly or writeonly as requested */
64
                switch (right) {
65
                        case O_RDONLY:
66
                                finfo.access = O_RDONLY;
67
                                result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
68
                                        NULL, NULL, OC_MODE_OPEN,
69
                                        0, AR_READ, &finfo);
70
                                break;
71
                        case O_WRONLY:
72
                                finfo.access = O_WRONLY;
73
                                result = ncp_open_create_file_or_subdir(NCP_SERVER(inode),
74
                                        NULL, NULL, OC_MODE_OPEN,
75
                                        0, AR_WRITE, &finfo);
76
                                break;
77
                }
78
                if (result) {
79
                        PPRINTK("ncp_make_open: failed, result=%d\n", result);
80
                        goto out_unlock;
81
                }
82
                /*
83
                 * Update the inode information.
84
                 */
85
        update:
86
                ncp_update_inode(inode, &finfo);
87
                atomic_set(&NCP_FINFO(inode)->opened, 1);
88
        }
89
 
90
        access = NCP_FINFO(inode)->access;
91
        PPRINTK("ncp_make_open: file open, access=%x\n", access);
92
        if (access == right || access == O_RDWR) {
93
                atomic_inc(&NCP_FINFO(inode)->opened);
94
                error = 0;
95
        }
96
 
97
out_unlock:
98
        up(&NCP_FINFO(inode)->open_sem);
99
out:
100
        return error;
101
}
102
 
103
static ssize_t
104
ncp_file_read(struct file *file, char *buf, size_t count, loff_t *ppos)
105
{
106
        struct dentry *dentry = file->f_dentry;
107
        struct inode *inode = dentry->d_inode;
108
        size_t already_read = 0;
109
        off_t pos;
110
        size_t bufsize;
111
        int error;
112
        void* freepage;
113
        size_t freelen;
114
 
115
        DPRINTK("ncp_file_read: enter %s/%s\n",
116
                dentry->d_parent->d_name.name, dentry->d_name.name);
117
 
118
        error = -EIO;
119
        if (!ncp_conn_valid(NCP_SERVER(inode)))
120
                goto out;
121
        error = -EINVAL;
122
        if (!S_ISREG(inode->i_mode)) {
123
                DPRINTK("ncp_file_read: read from non-file, mode %07o\n",
124
                        inode->i_mode);
125
                goto out;
126
        }
127
 
128
        pos = *ppos;
129
/* leave it out on server ...
130
        if (pos + count > inode->i_size) {
131
                count = inode->i_size - pos;
132
        }
133
*/
134
        error = 0;
135
        if (!count)     /* size_t is never < 0 */
136
                goto out;
137
 
138
        error = ncp_make_open(inode, O_RDONLY);
139
        if (error) {
140
                DPRINTK(KERN_ERR "ncp_file_read: open failed, error=%d\n", error);
141
                goto out;
142
        }
143
 
144
        bufsize = NCP_SERVER(inode)->buffer_size;
145
 
146
        error = -EIO;
147
        freelen = ncp_read_bounce_size(bufsize);
148
        freepage = vmalloc(freelen);
149
        if (!freepage)
150
                goto outrel;
151
        error = 0;
152
        /* First read in as much as possible for each bufsize. */
153
        while (already_read < count) {
154
                int read_this_time;
155
                size_t to_read = min_t(unsigned int,
156
                                     bufsize - (pos % bufsize),
157
                                     count - already_read);
158
 
159
                error = ncp_read_bounce(NCP_SERVER(inode),
160
                                NCP_FINFO(inode)->file_handle,
161
                                pos, to_read, buf, &read_this_time,
162
                                freepage, freelen);
163
                if (error) {
164
                        error = -EIO;   /* NW errno -> Linux errno */
165
                        break;
166
                }
167
                pos += read_this_time;
168
                buf += read_this_time;
169
                already_read += read_this_time;
170
 
171
                if (read_this_time != to_read) {
172
                        break;
173
                }
174
        }
175
        vfree(freepage);
176
 
177
        *ppos = pos;
178
 
179
        if (!IS_RDONLY(inode)) {
180
                inode->i_atime = CURRENT_TIME;
181
        }
182
 
183
        DPRINTK("ncp_file_read: exit %s/%s\n",
184
                dentry->d_parent->d_name.name, dentry->d_name.name);
185
outrel:
186
        ncp_inode_close(inode);
187
out:
188
        return already_read ? already_read : error;
189
}
190
 
191
static ssize_t
192
ncp_file_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
193
{
194
        struct dentry *dentry = file->f_dentry;
195
        struct inode *inode = dentry->d_inode;
196
        size_t already_written = 0;
197
        off_t pos;
198
        size_t bufsize;
199
        int errno;
200
        void* bouncebuffer;
201
 
202
        DPRINTK("ncp_file_write: enter %s/%s\n",
203
                dentry->d_parent->d_name.name, dentry->d_name.name);
204
        errno = -EIO;
205
        if (!ncp_conn_valid(NCP_SERVER(inode)))
206
                goto out;
207
        if (!S_ISREG(inode->i_mode)) {
208
                DPRINTK("ncp_file_write: write to non-file, mode %07o\n",
209
                        inode->i_mode);
210
                return -EINVAL;
211
        }
212
 
213
        errno = 0;
214
        if (!count)
215
                goto out;
216
        errno = ncp_make_open(inode, O_WRONLY);
217
        if (errno) {
218
                DPRINTK(KERN_ERR "ncp_file_write: open failed, error=%d\n", errno);
219
                return errno;
220
        }
221
        pos = *ppos;
222
 
223
        if (file->f_flags & O_APPEND) {
224
                pos = inode->i_size;
225
        }
226
        bufsize = NCP_SERVER(inode)->buffer_size;
227
 
228
        already_written = 0;
229
 
230
        bouncebuffer = vmalloc(bufsize);
231
        if (!bouncebuffer) {
232
                errno = -EIO;   /* -ENOMEM */
233
                goto outrel;
234
        }
235
        while (already_written < count) {
236
                int written_this_time;
237
                size_t to_write = min_t(unsigned int,
238
                                      bufsize - (pos % bufsize),
239
                                      count - already_written);
240
 
241
                if (copy_from_user(bouncebuffer, buf, to_write)) {
242
                        errno = -EFAULT;
243
                        break;
244
                }
245
                if (ncp_write_kernel(NCP_SERVER(inode),
246
                    NCP_FINFO(inode)->file_handle,
247
                    pos, to_write, bouncebuffer, &written_this_time) != 0) {
248
                        errno = -EIO;
249
                        break;
250
                }
251
                pos += written_this_time;
252
                buf += written_this_time;
253
                already_written += written_this_time;
254
 
255
                if (written_this_time != to_write) {
256
                        break;
257
                }
258
        }
259
        vfree(bouncebuffer);
260
        inode->i_mtime = inode->i_atime = CURRENT_TIME;
261
 
262
        *ppos = pos;
263
 
264
        if (pos > inode->i_size) {
265
                inode->i_size = pos;
266
        }
267
        DPRINTK("ncp_file_write: exit %s/%s\n",
268
                dentry->d_parent->d_name.name, dentry->d_name.name);
269
outrel:
270
        ncp_inode_close(inode);
271
out:
272
        return already_written ? already_written : errno;
273
}
274
 
275
static int ncp_release(struct inode *inode, struct file *file) {
276
        if (ncp_make_closed(inode)) {
277
                DPRINTK("ncp_release: failed to close\n");
278
        }
279
        return 0;
280
}
281
 
282
struct file_operations ncp_file_operations =
283
{
284
        llseek:         generic_file_llseek,
285
        read:           ncp_file_read,
286
        write:          ncp_file_write,
287
        ioctl:          ncp_ioctl,
288
        mmap:           ncp_mmap,
289
        release:        ncp_release,
290
        fsync:          ncp_fsync,
291
};
292
 
293
struct inode_operations ncp_file_inode_operations =
294
{
295
        setattr:        ncp_notify_change,
296
};

powered by: WebSVN 2.1.0

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