Blame view
fs/udf/symlink.c
2.99 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 |
/* * symlink.c * * PURPOSE * Symlink handling routines for the OSTA-UDF(tm) filesystem. * |
1da177e4c Linux-2.6.12-rc2 |
7 8 9 10 11 12 13 |
* COPYRIGHT * This file is distributed under the terms of the GNU General Public * License (GPL). Copies of the GPL can be obtained from: * ftp://prep.ai.mit.edu/pub/gnu/GPL * Each contributing author retains all rights to their own work. * * (C) 1998-2001 Ben Fennema |
28de7948a UDF: coding style... |
14 |
* (C) 1999 Stelias Computing Inc |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 18 19 20 21 22 |
* * HISTORY * * 04/16/99 blf Created. * */ #include "udfdecl.h" |
e973606cc udf: use linux/ua... |
23 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
24 25 |
#include <linux/errno.h> #include <linux/fs.h> |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 |
#include <linux/time.h> #include <linux/mm.h> #include <linux/stat.h> |
1da177e4c Linux-2.6.12-rc2 |
29 |
#include <linux/pagemap.h> |
1da177e4c Linux-2.6.12-rc2 |
30 31 |
#include <linux/buffer_head.h> #include "udf_i.h" |
1a927faa5 udf: Check path l... |
32 33 |
static int udf_pc_to_char(struct super_block *sb, unsigned char *from, int fromlen, unsigned char *to, int tolen) |
1da177e4c Linux-2.6.12-rc2 |
34 35 36 |
{ struct pathComponent *pc; int elen = 0; |
1a927faa5 udf: Check path l... |
37 |
int comp_len; |
391e8bbd3 sanitize const/si... |
38 |
unsigned char *p = to; |
1da177e4c Linux-2.6.12-rc2 |
39 |
|
1a927faa5 udf: Check path l... |
40 41 |
/* Reserve one byte for terminating \0 */ tolen--; |
cb00ea352 UDF: coding style... |
42 |
while (elen < fromlen) { |
1da177e4c Linux-2.6.12-rc2 |
43 |
pc = (struct pathComponent *)(from + elen); |
cb00ea352 UDF: coding style... |
44 45 |
switch (pc->componentType) { case 1: |
fef2e9f33 udf: Treat symlin... |
46 47 48 49 50 51 52 53 |
/* * Symlink points to some place which should be agreed * upon between originator and receiver of the media. Ignore. */ if (pc->lengthComponentIdent > 0) break; /* Fall through */ case 2: |
1a927faa5 udf: Check path l... |
54 55 |
if (tolen == 0) return -ENAMETOOLONG; |
fef2e9f33 udf: Treat symlin... |
56 57 |
p = to; *p++ = '/'; |
1a927faa5 udf: Check path l... |
58 |
tolen--; |
cb00ea352 UDF: coding style... |
59 60 |
break; case 3: |
1a927faa5 udf: Check path l... |
61 62 |
if (tolen < 3) return -ENAMETOOLONG; |
cb00ea352 UDF: coding style... |
63 64 |
memcpy(p, "../", 3); p += 3; |
1a927faa5 udf: Check path l... |
65 |
tolen -= 3; |
cb00ea352 UDF: coding style... |
66 67 |
break; case 4: |
1a927faa5 udf: Check path l... |
68 69 |
if (tolen < 2) return -ENAMETOOLONG; |
cb00ea352 UDF: coding style... |
70 71 |
memcpy(p, "./", 2); p += 2; |
1a927faa5 udf: Check path l... |
72 |
tolen -= 2; |
cb00ea352 UDF: coding style... |
73 74 75 |
/* that would be . - just ignore */ break; case 5: |
1a927faa5 udf: Check path l... |
76 77 78 79 80 81 82 |
comp_len = udf_get_filename(sb, pc->componentIdent, pc->lengthComponentIdent, p, tolen); p += comp_len; tolen -= comp_len; if (tolen == 0) return -ENAMETOOLONG; |
cb00ea352 UDF: coding style... |
83 |
*p++ = '/'; |
1a927faa5 udf: Check path l... |
84 |
tolen--; |
cb00ea352 UDF: coding style... |
85 |
break; |
1da177e4c Linux-2.6.12-rc2 |
86 87 88 |
} elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; } |
cb00ea352 UDF: coding style... |
89 |
if (p > to + 1) |
1da177e4c Linux-2.6.12-rc2 |
90 91 92 |
p[-1] = '\0'; else p[0] = '\0'; |
1a927faa5 udf: Check path l... |
93 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
94 95 96 97 98 99 |
} static int udf_symlink_filler(struct file *file, struct page *page) { struct inode *inode = page->mapping->host; struct buffer_head *bh = NULL; |
391e8bbd3 sanitize const/si... |
100 |
unsigned char *symlink; |
1da177e4c Linux-2.6.12-rc2 |
101 |
int err = -EIO; |
391e8bbd3 sanitize const/si... |
102 |
unsigned char *p = kmap(page); |
48d6d8ff7 udf: cache struct... |
103 |
struct udf_inode_info *iinfo; |
4d0fb621d udf: Replace bkl ... |
104 |
uint32_t pos; |
1da177e4c Linux-2.6.12-rc2 |
105 |
|
48d6d8ff7 udf: cache struct... |
106 |
iinfo = UDF_I(inode); |
4d0fb621d udf: Replace bkl ... |
107 108 109 |
pos = udf_block_map(inode, 0); down_read(&iinfo->i_data_sem); |
48d6d8ff7 udf: cache struct... |
110 111 |
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr; |
28de7948a UDF: coding style... |
112 |
} else { |
4d0fb621d udf: Replace bkl ... |
113 |
bh = sb_bread(inode->i_sb, pos); |
1da177e4c Linux-2.6.12-rc2 |
114 115 116 117 118 119 |
if (!bh) goto out; symlink = bh->b_data; } |
1a927faa5 udf: Check path l... |
120 |
err = udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p, PAGE_SIZE); |
3bf25cb40 udf: use get_bh() |
121 |
brelse(bh); |
1a927faa5 udf: Check path l... |
122 123 |
if (err) goto out_unlock_inode; |
1da177e4c Linux-2.6.12-rc2 |
124 |
|
4d0fb621d udf: Replace bkl ... |
125 |
up_read(&iinfo->i_data_sem); |
1da177e4c Linux-2.6.12-rc2 |
126 127 128 129 |
SetPageUptodate(page); kunmap(page); unlock_page(page); return 0; |
28de7948a UDF: coding style... |
130 131 |
out: |
4d0fb621d udf: Replace bkl ... |
132 |
up_read(&iinfo->i_data_sem); |
1da177e4c Linux-2.6.12-rc2 |
133 134 135 136 137 138 139 140 141 |
SetPageError(page); kunmap(page); unlock_page(page); return err; } /* * symlinks can't do much... */ |
f5e54d6e5 [PATCH] mark addr... |
142 |
const struct address_space_operations udf_symlink_aops = { |
28de7948a UDF: coding style... |
143 |
.readpage = udf_symlink_filler, |
1da177e4c Linux-2.6.12-rc2 |
144 |
}; |