Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * symlink.c
  3  *
  4  * PURPOSE
  5  *      Symlink handling routines for the OSTA-UDF(tm) filesystem.
  6  *
  7  * COPYRIGHT
  8  *      This file is distributed under the terms of the GNU General Public
  9  *      License (GPL). Copies of the GPL can be obtained from:
 10  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
 11  *      Each contributing author retains all rights to their own work.
 12  *
 13  *  (C) 1998-2001 Ben Fennema
 14  *  (C) 1999 Stelias Computing Inc
 15  *
 16  * HISTORY
 17  *
 18  *  04/16/99 blf  Created.
 19  *
 20  */
 21 
 22 #include "udfdecl.h"
 23 #include <asm/uaccess.h>
 24 #include <linux/errno.h>
 25 #include <linux/fs.h>
 26 #include <linux/time.h>
 27 #include <linux/mm.h>
 28 #include <linux/stat.h>
 29 #include <linux/slab.h>
 30 #include <linux/pagemap.h>
 31 #include <linux/smp_lock.h>
 32 #include <linux/buffer_head.h>
 33 #include "udf_i.h"
 34 
 35 static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen,
 36                            char *to)
 37 {
 38         struct pathComponent *pc;
 39         int elen = 0;
 40         char *p = to;
 41 
 42         while (elen < fromlen) {
 43                 pc = (struct pathComponent *)(from + elen);
 44                 switch (pc->componentType) {
 45                 case 1:
 46                         if (pc->lengthComponentIdent == 0) {
 47                                 p = to;
 48                                 *p++ = '/';
 49                         }
 50                         break;
 51                 case 3:
 52                         memcpy(p, "../", 3);
 53                         p += 3;
 54                         break;
 55                 case 4:
 56                         memcpy(p, "./", 2);
 57                         p += 2;
 58                         /* that would be . - just ignore */
 59                         break;
 60                 case 5:
 61                         p += udf_get_filename(sb, pc->componentIdent, p,
 62                                               pc->lengthComponentIdent);
 63                         *p++ = '/';
 64                         break;
 65                 }
 66                 elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
 67         }
 68         if (p > to + 1)
 69                 p[-1] = '\0';
 70         else
 71                 p[0] = '\0';
 72 }
 73 
 74 static int udf_symlink_filler(struct file *file, struct page *page)
 75 {
 76         struct inode *inode = page->mapping->host;
 77         struct buffer_head *bh = NULL;
 78         char *symlink;
 79         int err = -EIO;
 80         char *p = kmap(page);
 81         struct udf_inode_info *iinfo;
 82 
 83         lock_kernel();
 84         iinfo = UDF_I(inode);
 85         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
 86                 symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
 87         } else {
 88                 bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
 89 
 90                 if (!bh)
 91                         goto out;
 92 
 93                 symlink = bh->b_data;
 94         }
 95 
 96         udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
 97         brelse(bh);
 98 
 99         unlock_kernel();
100         SetPageUptodate(page);
101         kunmap(page);
102         unlock_page(page);
103         return 0;
104 
105 out:
106         unlock_kernel();
107         SetPageError(page);
108         kunmap(page);
109         unlock_page(page);
110         return err;
111 }
112 
113 /*
114  * symlinks can't do much...
115  */
116 const struct address_space_operations udf_symlink_aops = {
117         .readpage               = udf_symlink_filler,
118 };
119 
  This page was automatically generated by the LXR engine.