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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/fs/hfs/file.c
3
 *
4
 * Copyright (C) 1995, 1996  Paul H. Hargrove
5
 * This file may be distributed under the terms of the GNU General Public License.
6
 *
7
 * This file contains the file-related functions which are independent of
8
 * which scheme is being used to represent forks.
9
 *
10
 * Based on the minix file system code, (C) 1991, 1992 by Linus Torvalds
11
 *
12
 * "XXX" in a comment is a note to myself to consider changing something.
13
 *
14
 * In function preconditions the term "valid" applied to a pointer to
15
 * a structure means that the pointer is non-NULL and the structure it
16
 * points to has all fields initialized to consistent values.
17
 */
18
 
19
#include "hfs.h"
20
#include <linux/hfs_fs_sb.h>
21
#include <linux/hfs_fs_i.h>
22
#include <linux/hfs_fs.h>
23
 
24
/*================ Forward declarations ================*/
25
 
26
static hfs_rwret_t hfs_file_read(struct file *, char *, hfs_rwarg_t,
27
                                 loff_t *);
28
static hfs_rwret_t hfs_file_write(struct file *, const char *, hfs_rwarg_t,
29
                                  loff_t *);
30
static void hfs_file_truncate(struct inode *);
31
 
32
/*================ Global variables ================*/
33
 
34
struct file_operations hfs_file_operations = {
35
        llseek:         generic_file_llseek,
36
        read:           hfs_file_read,
37
        write:          hfs_file_write,
38
        mmap:           generic_file_mmap,
39
        fsync:          file_fsync,
40
};
41
 
42
struct inode_operations hfs_file_inode_operations = {
43
        truncate:       hfs_file_truncate,
44
        setattr:        hfs_notify_change,
45
};
46
 
47
/*================ Variable-like macros ================*/
48
 
49
/* maximum number of blocks to try to read in at once */
50
#define NBUF 32
51
 
52
/*================ File-local functions ================*/
53
 
54
/*
55
 * hfs_getblk()
56
 *
57
 * Given an hfs_fork and a block number return the buffer_head for
58
 * that block from the fork.  If 'create' is non-zero then allocate
59
 * the necessary block(s) to the fork.
60
 */
61
struct buffer_head *hfs_getblk(struct hfs_fork *fork, int block, int create)
62
{
63
        int tmp;
64
        struct super_block *sb = fork->entry->mdb->sys_mdb;
65
 
66
        tmp = hfs_extent_map(fork, block, create);
67
 
68
        if (create) {
69
                /* If writing the block, then we have exclusive access
70
                   to the file until we return, so it can't have moved.
71
                */
72
                if (tmp) {
73
                        hfs_cat_mark_dirty(fork->entry);
74
                        return sb_getblk(sb, tmp);
75
                }
76
                return NULL;
77
        } else {
78
                /* If reading the block, then retry since the
79
                   location on disk could have changed while
80
                   we waited on the I/O in getblk to complete.
81
                */
82
                do {
83
                        struct buffer_head *bh = sb_getblk(sb, tmp);
84
                        int tmp2 = hfs_extent_map(fork, block, 0);
85
 
86
                        if (tmp2 == tmp) {
87
                                return bh;
88
                        } else {
89
                                /* The block moved or no longer exists. */
90
                                brelse(bh);
91
                                tmp = tmp2;
92
                        }
93
                } while (tmp != 0);
94
 
95
                /* The block no longer exists. */
96
                return NULL;
97
        }
98
}
99
 
100
/*
101
 * hfs_get_block
102
 *
103
 * This is the hfs_get_block() field in the inode_operations structure for
104
 * "regular" (non-header) files.  The purpose is to translate an inode
105
 * and a block number within the corresponding file into a physical
106
 * block number.  This function just calls hfs_extent_map() to do the
107
 * real work and then stuffs the appropriate info into the buffer_head.
108
 */
109
int hfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
110
{
111
        unsigned long phys;
112
 
113
        phys = hfs_extent_map(HFS_I(inode)->fork, iblock, create);
114
        if (phys) {
115
                bh_result->b_dev = inode->i_dev;
116
                bh_result->b_blocknr = phys;
117
                bh_result->b_state |= (1UL << BH_Mapped);
118
                if (create)
119
                        bh_result->b_state |= (1UL << BH_New);
120
                return 0;
121
        }
122
 
123
        if (!create)
124
                return 0;
125
 
126
        /* we tried to add stuff, but we couldn't. send back an out-of-space
127
         * error. */
128
        return -ENOSPC;
129
}
130
 
131
 
132
/*
133
 * hfs_file_read()
134
 *
135
 * This is the read field in the inode_operations structure for
136
 * "regular" (non-header) files.  The purpose is to transfer up to
137
 * 'count' bytes from the file corresponding to 'inode', beginning at
138
 * 'filp->offset' bytes into the file.  The data is transferred to
139
 * user-space at the address 'buf'.  Returns the number of bytes
140
 * successfully transferred.  This function checks the arguments, does
141
 * some setup and then calls hfs_do_read() to do the actual transfer.  */
142
static hfs_rwret_t hfs_file_read(struct file * filp, char * buf,
143
                                 hfs_rwarg_t count, loff_t *ppos)
144
{
145
        struct inode *inode = filp->f_dentry->d_inode;
146
        hfs_s32 read, left, pos, size;
147
 
148
        if (!S_ISREG(inode->i_mode)) {
149
                hfs_warn("hfs_file_read: mode = %07o\n",inode->i_mode);
150
                return -EINVAL;
151
        }
152
        pos = *ppos;
153
        if (pos >= HFS_FORK_MAX) {
154
                return 0;
155
        }
156
        size = inode->i_size;
157
        if (pos > size) {
158
                left = 0;
159
        } else {
160
                left = size - pos;
161
        }
162
        if (left > count) {
163
                left = count;
164
        }
165
        if (left <= 0) {
166
                return 0;
167
        }
168
        if ((read = hfs_do_read(inode, HFS_I(inode)->fork, pos,
169
                                buf, left, filp->f_reada != 0)) > 0) {
170
                *ppos += read;
171
                filp->f_reada = 1;
172
        }
173
 
174
        return read;
175
}
176
 
177
/*
178
 * hfs_file_write()
179
 *
180
 * This is the write() entry in the file_operations structure for
181
 * "regular" files.  The purpose is to transfer up to 'count' bytes
182
 * to the file corresponding to 'inode' beginning at offset
183
 * 'file->f_pos' from user-space at the address 'buf'.  The return
184
 * value is the number of bytes actually transferred.
185
 */
186
static hfs_rwret_t hfs_file_write(struct file * filp, const char * buf,
187
                                  hfs_rwarg_t count, loff_t *ppos)
188
{
189
        struct inode    *inode = filp->f_dentry->d_inode;
190
        struct hfs_fork *fork = HFS_I(inode)->fork;
191
        hfs_s32 written, pos;
192
 
193
        if (!S_ISREG(inode->i_mode)) {
194
                hfs_warn("hfs_file_write: mode = %07o\n", inode->i_mode);
195
                return -EINVAL;
196
        }
197
 
198
        pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
199
 
200
        if (pos >= HFS_FORK_MAX) {
201
                return 0;
202
        }
203
        if (count > HFS_FORK_MAX) {
204
                count = HFS_FORK_MAX;
205
        }
206
        if ((written = hfs_do_write(inode, fork, pos, buf, count)) > 0)
207
                pos += written;
208
 
209
        *ppos = pos;
210
        if (*ppos > inode->i_size) {
211
                inode->i_size = *ppos;
212
                mark_inode_dirty(inode);
213
        }
214
 
215
        return written;
216
}
217
 
218
/*
219
 * hfs_file_truncate()
220
 *
221
 * This is the truncate() entry in the file_operations structure for
222
 * "regular" files.  The purpose is to change the length of the file
223
 * corresponding to the given inode.  Changes can either lengthen or
224
 * shorten the file.
225
 */
226
static void hfs_file_truncate(struct inode * inode)
227
{
228
        struct hfs_fork *fork = HFS_I(inode)->fork;
229
 
230
        fork->lsize = inode->i_size;
231
        hfs_extent_adj(fork);
232
        hfs_cat_mark_dirty(HFS_I(inode)->entry);
233
 
234
        inode->i_size = fork->lsize;
235
        inode->i_blocks = fork->psize;
236
        mark_inode_dirty(inode);
237
}
238
 
239
/*
240
 * xlate_to_user()
241
 *
242
 * Like copy_to_user() while translating CR->NL.
243
 */
244
static inline void xlate_to_user(char *buf, const char *data, int count)
245
{
246
        char ch;
247
 
248
        while (count--) {
249
                ch = *(data++);
250
                put_user((ch == '\r') ? '\n' : ch, buf++);
251
        }
252
}
253
 
254
/*
255
 * xlate_from_user()
256
 *
257
 * Like copy_from_user() while translating NL->CR;
258
 */
259
static inline int xlate_from_user(char *data, const char *buf, int count)
260
{
261
        int i;
262
 
263
        i = copy_from_user(data, buf, count);
264
        count -= i;
265
        while (count--) {
266
                if (*data == '\n') {
267
                        *data = '\r';
268
                }
269
                ++data;
270
        }
271
        return i;
272
}
273
 
274
/*================ Global functions ================*/
275
 
276
/*
277
 * hfs_do_read()
278
 *
279
 * This function transfers actual data from disk to user-space memory,
280
 * returning the number of bytes successfully transferred.  'fork' tells
281
 * which file on the disk to read from.  'pos' gives the offset into
282
 * the Linux file at which to begin the transfer.  Note that this will
283
 * differ from 'filp->offset' in the case of an AppleDouble header file
284
 * due to the block of metadata at the beginning of the file, which has
285
 * no corresponding place in the HFS file.  'count' tells how many
286
 * bytes to transfer.  'buf' gives an address in user-space to transfer
287
 * the data to.
288
 *
289
 * This is based on Linus's minix_file_read().
290
 * It has been changed to take into account that HFS files have no holes.
291
 */
292
hfs_s32 hfs_do_read(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos,
293
                    char * buf, hfs_u32 count, int reada)
294
{
295
        kdev_t dev = inode->i_dev;
296
        hfs_s32 size, chars, offset, block, blocks, read = 0;
297
        int bhrequest, uptodate;
298
        int convert = HFS_I(inode)->convert;
299
        struct buffer_head ** bhb, ** bhe;
300
        struct buffer_head * bhreq[NBUF];
301
        struct buffer_head * buflist[NBUF];
302
 
303
        /* split 'pos' in to block and (byte) offset components */
304
        block = pos >> HFS_SECTOR_SIZE_BITS;
305
        offset = pos & (HFS_SECTOR_SIZE-1);
306
 
307
        /* compute the logical size of the fork in blocks */
308
        size = (fork->lsize + (HFS_SECTOR_SIZE-1)) >> HFS_SECTOR_SIZE_BITS;
309
 
310
        /* compute the number of physical blocks to be transferred */
311
        blocks = (count+offset+HFS_SECTOR_SIZE-1) >> HFS_SECTOR_SIZE_BITS;
312
 
313
        bhb = bhe = buflist;
314
        if (reada) {
315
                if (blocks < read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9)) {
316
                        blocks = read_ahead[MAJOR(dev)] / (HFS_SECTOR_SIZE>>9);
317
                }
318
                if (block + blocks > size) {
319
                        blocks = size - block;
320
                }
321
        }
322
 
323
        /* We do this in a two stage process.  We first try and
324
           request as many blocks as we can, then we wait for the
325
           first one to complete, and then we try and wrap up as many
326
           as are actually done.
327
 
328
           This routine is optimized to make maximum use of the
329
           various buffers and caches. */
330
 
331
        do {
332
                bhrequest = 0;
333
                uptodate = 1;
334
                while (blocks) {
335
                        --blocks;
336
                        *bhb = hfs_getblk(fork, block++, 0);
337
 
338
                        if (!(*bhb)) {
339
                                /* Since there are no holes in HFS files
340
                                   we must have encountered an error.
341
                                   So, stop adding blocks to the queue. */
342
                                blocks = 0;
343
                                break;
344
                        }
345
 
346
                        if (!buffer_uptodate(*bhb)) {
347
                                uptodate = 0;
348
                                bhreq[bhrequest++] = *bhb;
349
                        }
350
 
351
                        if (++bhb == &buflist[NBUF]) {
352
                                bhb = buflist;
353
                        }
354
 
355
                        /* If the block we have on hand is uptodate,
356
                           go ahead and complete processing. */
357
                        if (uptodate) {
358
                                break;
359
                        }
360
                        if (bhb == bhe) {
361
                                break;
362
                        }
363
                }
364
 
365
                /* If the only block in the queue is bad then quit */
366
                if (!(*bhe)) {
367
                        break;
368
                }
369
 
370
                /* Now request them all */
371
                if (bhrequest) {
372
                        ll_rw_block(READ, bhrequest, bhreq);
373
                }
374
 
375
                do {  /* Finish off all I/O that has actually completed */
376
                        char *p;
377
 
378
                        wait_on_buffer(*bhe);
379
 
380
                        if (!buffer_uptodate(*bhe)) {
381
                                /* read error? */
382
                                brelse(*bhe);
383
                                if (++bhe == &buflist[NBUF]) {
384
                                        bhe = buflist;
385
                                }
386
                                count = 0;
387
                                break;
388
                        }
389
 
390
                        if (count < HFS_SECTOR_SIZE - offset) {
391
                                chars = count;
392
                        } else {
393
                                chars = HFS_SECTOR_SIZE - offset;
394
                        }
395
                        p = (*bhe)->b_data + offset;
396
                        if (convert) {
397
                                xlate_to_user(buf, p, chars);
398
                        } else {
399
                                chars -= copy_to_user(buf, p, chars);
400
                                if (!chars) {
401
                                        brelse(*bhe);
402
                                        count = 0;
403
                                        if (!read)
404
                                                read = -EFAULT;
405
                                        break;
406
                                }
407
                        }
408
                        brelse(*bhe);
409
                        count -= chars;
410
                        buf += chars;
411
                        read += chars;
412
                        offset = 0;
413
                        if (++bhe == &buflist[NBUF]) {
414
                                bhe = buflist;
415
                        }
416
                } while (count && (bhe != bhb) && !buffer_locked(*bhe));
417
        } while (count);
418
 
419
        /* Release the read-ahead blocks */
420
        while (bhe != bhb) {
421
                brelse(*bhe);
422
                if (++bhe == &buflist[NBUF]) {
423
                        bhe = buflist;
424
                }
425
        }
426
        if (!read) {
427
                return -EIO;
428
        }
429
        return read;
430
}
431
 
432
/*
433
 * hfs_do_write()
434
 *
435
 * This function transfers actual data from user-space memory to disk,
436
 * returning the number of bytes successfully transferred.  'fork' tells
437
 * which file on the disk to write to.  'pos' gives the offset into
438
 * the Linux file at which to begin the transfer.  Note that this will
439
 * differ from 'filp->offset' in the case of an AppleDouble header file
440
 * due to the block of metadata at the beginning of the file, which has
441
 * no corresponding place in the HFS file.  'count' tells how many
442
 * bytes to transfer.  'buf' gives an address in user-space to transfer
443
 * the data from.
444
 *
445
 * This is just a minor edit of Linus's minix_file_write().
446
 */
447
hfs_s32 hfs_do_write(struct inode *inode, struct hfs_fork * fork, hfs_u32 pos,
448
                     const char * buf, hfs_u32 count)
449
{
450
        hfs_s32 written, c;
451
        struct buffer_head * bh;
452
        char * p;
453
        int convert = HFS_I(inode)->convert;
454
 
455
        written = 0;
456
        while (written < count) {
457
                bh = hfs_getblk(fork, pos/HFS_SECTOR_SIZE, 1);
458
                if (!bh) {
459
                        if (!written) {
460
                                written = -ENOSPC;
461
                        }
462
                        break;
463
                }
464
                c = HFS_SECTOR_SIZE - (pos % HFS_SECTOR_SIZE);
465
                if (c > count - written) {
466
                        c = count - written;
467
                }
468
                if (c != HFS_SECTOR_SIZE && !buffer_uptodate(bh)) {
469
                        ll_rw_block(READ, 1, &bh);
470
                        wait_on_buffer(bh);
471
                        if (!buffer_uptodate(bh)) {
472
                                brelse(bh);
473
                                if (!written) {
474
                                        written = -EIO;
475
                                }
476
                                break;
477
                        }
478
                }
479
                p = (pos % HFS_SECTOR_SIZE) + bh->b_data;
480
                c -= convert ? xlate_from_user(p, buf, c) :
481
                        copy_from_user(p, buf, c);
482
                if (!c) {
483
                        brelse(bh);
484
                        if (!written)
485
                                written = -EFAULT;
486
                        break;
487
                }
488
                pos += c;
489
                written += c;
490
                buf += c;
491
                mark_buffer_uptodate(bh, 1);
492
                mark_buffer_dirty(bh);
493
                brelse(bh);
494
        }
495
        if (written > 0) {
496
                struct hfs_cat_entry *entry = fork->entry;
497
 
498
                inode->i_mtime = inode->i_ctime = CURRENT_TIME;
499
                if (pos > fork->lsize) {
500
                        fork->lsize = pos;
501
                }
502
                entry->modify_date = hfs_u_to_mtime(CURRENT_TIME);
503
                hfs_cat_mark_dirty(entry);
504
        }
505
        return written;
506
}
507
 
508
/*
509
 * hfs_file_fix_mode()
510
 *
511
 * Fixes up the permissions on a file after changing the write-inhibit bit.
512
 */
513
void hfs_file_fix_mode(struct hfs_cat_entry *entry)
514
{
515
        struct dentry **de = entry->sys_entry;
516
        int i;
517
 
518
        if (entry->u.file.flags & HFS_FIL_LOCK) {
519
                for (i = 0; i < 4; ++i) {
520
                        if (de[i]) {
521
                                de[i]->d_inode->i_mode &= ~S_IWUGO;
522
                        }
523
                }
524
        } else {
525
                for (i = 0; i < 4; ++i) {
526
                        if (de[i]) {
527
                                struct inode *inode = de[i]->d_inode;
528
                                inode->i_mode |= S_IWUGO;
529
                                inode->i_mode &=
530
                                  ~HFS_SB(inode->i_sb)->s_umask;
531
                        }
532
                }
533
        }
534
}

powered by: WebSVN 2.1.0

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