~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/hfs/file.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  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 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         read:           hfs_file_read,
 36         write:          hfs_file_write,
 37         mmap:           generic_file_mmap,
 38         fsync:          file_fsync,
 39 };
 40 
 41 struct inode_operations hfs_file_inode_operations = {
 42         truncate:       hfs_file_truncate,
 43         setattr:        hfs_notify_change,
 44 };
 45 
 46 /*================ Variable-like macros ================*/
 47 
 48 /* maximum number of blocks to try to read in at once */
 49 #define NBUF 32
 50 
 51 /*================ File-local functions ================*/
 52 
 53 /*
 54  * hfs_getblk()
 55  *
 56  * Given an hfs_fork and a block number return the buffer_head for
 57  * that block from the fork.  If 'create' is non-zero then allocate
 58  * the necessary block(s) to the fork.
 59  */
 60 struct buffer_head *hfs_getblk(struct hfs_fork *fork, int block, int create)
 61 {
 62         int tmp;
 63         kdev_t dev = fork->entry->mdb->sys_mdb->s_dev;
 64 
 65         tmp = hfs_extent_map(fork, block, create);
 66 
 67         if (create) {
 68                 /* If writing the block, then we have exclusive access
 69                    to the file until we return, so it can't have moved.
 70                 */
 71                 if (tmp) {
 72                         hfs_cat_mark_dirty(fork->entry);
 73                         return getblk(dev, tmp, HFS_SECTOR_SIZE);
 74                 }
 75                 return NULL;
 76         } else {
 77                 /* If reading the block, then retry since the
 78                    location on disk could have changed while
 79                    we waited on the I/O in getblk to complete.
 80                 */
 81                 do {
 82                         struct buffer_head *bh =
 83                                         getblk(dev, tmp, HFS_SECTOR_SIZE);
 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 transfered to
139  * user-space at the address 'buf'.  Returns the number of bytes
140  * successfully transfered.  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 transfered.  '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 transfered.  '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 }
535 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.