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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [udf/] [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
 * PURPOSE
5
 *  File handling routines for the OSTA-UDF(tm) filesystem.
6
 *
7
 * CONTACTS
8
 *  E-mail regarding any portion of the Linux UDF file system should be
9
 *  directed to the development team mailing list (run by majordomo):
10
 *    linux_udf@hpesjro.fc.hp.com
11
 *
12
 * COPYRIGHT
13
 *  This file is distributed under the terms of the GNU General Public
14
 *  License (GPL). Copies of the GPL can be obtained from:
15
 *    ftp://prep.ai.mit.edu/pub/gnu/GPL
16
 *  Each contributing author retains all rights to their own work.
17
 *
18
 *  (C) 1998-1999 Dave Boynton
19
 *  (C) 1998-2001 Ben Fennema
20
 *  (C) 1999-2000 Stelias Computing Inc
21
 *
22
 * HISTORY
23
 *
24
 *  10/02/98 dgb  Attempt to integrate into udf.o
25
 *  10/07/98      Switched to using generic_readpage, etc., like isofs
26
 *                And it works!
27
 *  12/06/98 blf  Added udf_file_read. uses generic_file_read for all cases but
28
 *                ICBTAG_FLAG_AD_IN_ICB.
29
 *  04/06/99      64 bit file handling on 32 bit systems taken from ext2 file.c
30
 *  05/12/99      Preliminary file write support
31
 */
32
 
33
#include "udfdecl.h"
34
#include <linux/fs.h>
35
#include <linux/udf_fs.h>
36
#include <asm/uaccess.h>
37
#include <linux/kernel.h>
38
#include <linux/string.h> /* memset */
39
#include <linux/errno.h>
40
#include <linux/locks.h>
41
#include <linux/smp_lock.h>
42
 
43
#include "udf_i.h"
44
#include "udf_sb.h"
45
 
46
static int udf_adinicb_readpage(struct file *file, struct page * page)
47
{
48
        struct inode *inode = page->mapping->host;
49
 
50
        struct buffer_head *bh;
51
        int block;
52
        char *kaddr;
53
        int err = 0;
54
 
55
        if (!PageLocked(page))
56
                PAGE_BUG(page);
57
 
58
        kaddr = kmap(page);
59
        memset(kaddr, 0, PAGE_CACHE_SIZE);
60
        block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
61
        bh = sb_bread(inode->i_sb, block);
62
        if (!bh)
63
        {
64
                SetPageError(page);
65
                err = -EIO;
66
                goto out;
67
        }
68
        memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
69
        brelse(bh);
70
        flush_dcache_page(page);
71
        SetPageUptodate(page);
72
out:
73
        kunmap(page);
74
        UnlockPage(page);
75
        return err;
76
}
77
 
78
static int udf_adinicb_writepage(struct page *page)
79
{
80
        struct inode *inode = page->mapping->host;
81
 
82
        struct buffer_head *bh;
83
        int block;
84
        char *kaddr;
85
        int err = 0;
86
 
87
        if (!PageLocked(page))
88
                PAGE_BUG(page);
89
 
90
        kaddr = kmap(page);
91
        block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
92
        bh = sb_bread(inode->i_sb, block);
93
        if (!bh)
94
        {
95
                SetPageError(page);
96
                err = -EIO;
97
                goto out;
98
        }
99
        memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
100
        mark_buffer_dirty(bh);
101
        brelse(bh);
102
        SetPageUptodate(page);
103
out:
104
        kunmap(page);
105
        UnlockPage(page);
106
        return err;
107
}
108
 
109
static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
110
{
111
        kmap(page);
112
        return 0;
113
}
114
 
115
static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
116
{
117
        struct inode *inode = page->mapping->host;
118
 
119
        struct buffer_head *bh;
120
        int block;
121
        char *kaddr = page_address(page);
122
        int err = 0;
123
 
124
        block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
125
        bh = sb_bread(inode->i_sb, block);
126
        if (!bh)
127
        {
128
                SetPageError(page);
129
                err = -EIO;
130
                goto out;
131
        }
132
        memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
133
                kaddr + offset, to - offset);
134
        mark_buffer_dirty(bh);
135
        brelse(bh);
136
        SetPageUptodate(page);
137
out:
138
        kunmap(page);
139
        /* only one page here */
140
        if (to > inode->i_size)
141
                inode->i_size = to;
142
        return err;
143
}
144
 
145
struct address_space_operations udf_adinicb_aops = {
146
        readpage:               udf_adinicb_readpage,
147
        writepage:              udf_adinicb_writepage,
148
        sync_page:              block_sync_page,
149
        prepare_write:          udf_adinicb_prepare_write,
150
        commit_write:           udf_adinicb_commit_write,
151
};
152
 
153
static ssize_t udf_file_write(struct file * file, const char * buf,
154
        size_t count, loff_t *ppos)
155
{
156
        ssize_t retval;
157
        struct inode *inode = file->f_dentry->d_inode;
158
        int err, pos;
159
 
160
        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
161
        {
162
                if (file->f_flags & O_APPEND)
163
                        pos = inode->i_size;
164
                else
165
                        pos = *ppos;
166
 
167
                if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
168
                        pos + count))
169
                {
170
                        udf_expand_file_adinicb(inode, pos + count, &err);
171
                        if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
172
                        {
173
                                udf_debug("udf_expand_adinicb: err=%d\n", err);
174
                                return err;
175
                        }
176
                }
177
                else
178
                {
179
                        if (pos + count > inode->i_size)
180
                                UDF_I_LENALLOC(inode) = pos + count;
181
                        else
182
                                UDF_I_LENALLOC(inode) = inode->i_size;
183
                }
184
        }
185
 
186
        retval = generic_file_write(file, buf, count, ppos);
187
 
188
        if (retval > 0)
189
        {
190
                UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
191
                mark_inode_dirty(inode);
192
        }
193
        return retval;
194
}
195
 
196
/*
197
 * udf_ioctl
198
 *
199
 * PURPOSE
200
 *      Issue an ioctl.
201
 *
202
 * DESCRIPTION
203
 *      Optional - sys_ioctl() will return -ENOTTY if this routine is not
204
 *      available, and the ioctl cannot be handled without filesystem help.
205
 *
206
 *      sys_ioctl() handles these ioctls that apply only to regular files:
207
 *              FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD
208
 *      These ioctls are also handled by sys_ioctl():
209
 *              FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC
210
 *      All other ioctls are passed to the filesystem.
211
 *
212
 *      Refer to sys_ioctl() in fs/ioctl.c
213
 *      sys_ioctl() -> .
214
 *
215
 * PRE-CONDITIONS
216
 *      inode                   Pointer to inode that ioctl was issued on.
217
 *      filp                    Pointer to file that ioctl was issued on.
218
 *      cmd                     The ioctl command.
219
 *      arg                     The ioctl argument [can be interpreted as a
220
 *                              user-space pointer if desired].
221
 *
222
 * POST-CONDITIONS
223
 *      <return>                Success (>=0) or an error code (<=0) that
224
 *                              sys_ioctl() will return.
225
 *
226
 * HISTORY
227
 *      July 1, 1997 - Andrew E. Mileski
228
 *      Written, tested, and released.
229
 */
230
int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
231
        unsigned long arg)
232
{
233
        int result = -EINVAL;
234
        struct buffer_head *bh = NULL;
235
        long_ad eaicb;
236
        uint8_t *ea = NULL;
237
 
238
        if ( permission(inode, MAY_READ) != 0 )
239
        {
240
                udf_debug("no permission to access inode %lu\n",
241
                                                inode->i_ino);
242
                return -EPERM;
243
        }
244
 
245
        if ( !arg )
246
        {
247
                udf_debug("invalid argument to udf_ioctl\n");
248
                return -EINVAL;
249
        }
250
 
251
        /* first, do ioctls that don't need to udf_read */
252
        switch (cmd)
253
        {
254
                case UDF_GETVOLIDENT:
255
                        return copy_to_user((char *)arg,
256
                                UDF_SB_VOLIDENT(inode->i_sb), 32) ? -EFAULT : 0;
257
                case UDF_RELOCATE_BLOCKS:
258
                {
259
                        long old, new;
260
 
261
                        if (!capable(CAP_SYS_ADMIN)) return -EACCES;
262
                        if (get_user(old, (long *)arg)) return -EFAULT;
263
                        if ((result = udf_relocate_blocks(inode->i_sb,
264
                                        old, &new)) == 0)
265
                                result = put_user(new, (long *)arg);
266
 
267
                        return result;
268
                }
269
        }
270
 
271
        /* ok, we need to read the inode */
272
        bh = udf_tread(inode->i_sb,
273
                udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
274
 
275
        if (!bh)
276
        {
277
                udf_debug("bread failed (inode=%ld)\n", inode->i_ino);
278
                return -EIO;
279
        }
280
 
281
        if (UDF_I_EXTENDED_FE(inode) == 0)
282
        {
283
                struct fileEntry *fe;
284
 
285
                fe = (struct fileEntry *)bh->b_data;
286
                eaicb = lela_to_cpu(fe->extendedAttrICB);
287
                if (UDF_I_LENEATTR(inode))
288
                        ea = fe->extendedAttr;
289
        }
290
        else
291
        {
292
                struct extendedFileEntry *efe;
293
 
294
                efe = (struct extendedFileEntry *)bh->b_data;
295
                eaicb = lela_to_cpu(efe->extendedAttrICB);
296
                if (UDF_I_LENEATTR(inode))
297
                        ea = efe->extendedAttr;
298
        }
299
 
300
        switch (cmd)
301
        {
302
                case UDF_GETEASIZE:
303
                        result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
304
                        break;
305
 
306
                case UDF_GETEABLOCK:
307
                        result = copy_to_user((char *)arg, ea,
308
                                UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
309
                        break;
310
        }
311
 
312
        udf_release_data(bh);
313
        return result;
314
}
315
 
316
/*
317
 * udf_release_file
318
 *
319
 * PURPOSE
320
 *  Called when all references to the file are closed
321
 *
322
 * DESCRIPTION
323
 *  Discard prealloced blocks
324
 *
325
 * HISTORY
326
 *
327
 */
328
static int udf_release_file(struct inode * inode, struct file * filp)
329
{
330
        if (filp->f_mode & FMODE_WRITE)
331
        {
332
                lock_kernel();
333
                udf_discard_prealloc(inode);
334
                unlock_kernel();
335
        }
336
        return 0;
337
}
338
 
339
/*
340
 * udf_open_file
341
 *
342
 * PURPOSE
343
 *  Called when an inode is about to be open.
344
 *
345
 * DESCRIPTION
346
 *  Use this to disallow opening RW large files on 32 bit systems.
347
 *  On 64 bit systems we force on O_LARGEFILE in sys_open.
348
 *
349
 * HISTORY
350
 *
351
 */
352
static int udf_open_file(struct inode * inode, struct file * filp)
353
{
354
        if ((inode->i_size & 0xFFFFFFFF80000000ULL) && !(filp->f_flags & O_LARGEFILE))
355
                return -EFBIG;
356
        return 0;
357
}
358
 
359
struct file_operations udf_file_operations = {
360
        read:                   generic_file_read,
361
        ioctl:                  udf_ioctl,
362
        open:                   udf_open_file,
363
        mmap:                   generic_file_mmap,
364
        write:                  udf_file_write,
365
        release:                udf_release_file,
366
        fsync:                  udf_fsync_file,
367
};
368
 
369
struct inode_operations udf_file_inode_operations = {
370
        truncate:               udf_truncate,
371
};

powered by: WebSVN 2.1.0

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