Blame view

fs/udf/symlink.c 2.56 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
  /*
   * symlink.c
   *
   * PURPOSE
   *	Symlink handling routines for the OSTA-UDF(tm) filesystem.
   *
1da177e4c   Linus Torvalds   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   Cyrill Gorcunov   UDF: coding style...
14
   *  (C) 1999 Stelias Computing Inc
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
16
17
18
19
20
21
22
23
24
25
   *
   * HISTORY
   *
   *  04/16/99 blf  Created.
   *
   */
  
  #include "udfdecl.h"
  #include <asm/uaccess.h>
  #include <linux/errno.h>
  #include <linux/fs.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
  #include <linux/time.h>
  #include <linux/mm.h>
  #include <linux/stat.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  #include <linux/pagemap.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
  #include <linux/buffer_head.h>
  #include "udf_i.h"
391e8bbd3   Al Viro   sanitize const/si...
32
33
  static void udf_pc_to_char(struct super_block *sb, unsigned char *from,
  			   int fromlen, unsigned char *to)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
35
36
  {
  	struct pathComponent *pc;
  	int elen = 0;
391e8bbd3   Al Viro   sanitize const/si...
37
  	unsigned char *p = to;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

cb00ea352   Cyrill Gorcunov   UDF: coding style...
39
  	while (elen < fromlen) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  		pc = (struct pathComponent *)(from + elen);
cb00ea352   Cyrill Gorcunov   UDF: coding style...
41
42
  		switch (pc->componentType) {
  		case 1:
fef2e9f33   Jan Kara   udf: Treat symlin...
43
44
45
46
47
48
49
50
51
52
  			/*
  			 * 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:
  			p = to;
  			*p++ = '/';
cb00ea352   Cyrill Gorcunov   UDF: coding style...
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  			break;
  		case 3:
  			memcpy(p, "../", 3);
  			p += 3;
  			break;
  		case 4:
  			memcpy(p, "./", 2);
  			p += 2;
  			/* that would be . - just ignore */
  			break;
  		case 5:
  			p += udf_get_filename(sb, pc->componentIdent, p,
  					      pc->lengthComponentIdent);
  			*p++ = '/';
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
70
  		}
  		elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
  	}
cb00ea352   Cyrill Gorcunov   UDF: coding style...
71
  	if (p > to + 1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
80
  		p[-1] = '\0';
  	else
  		p[0] = '\0';
  }
  
  static int udf_symlink_filler(struct file *file, struct page *page)
  {
  	struct inode *inode = page->mapping->host;
  	struct buffer_head *bh = NULL;
391e8bbd3   Al Viro   sanitize const/si...
81
  	unsigned char *symlink;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
  	int err = -EIO;
391e8bbd3   Al Viro   sanitize const/si...
83
  	unsigned char *p = kmap(page);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
84
  	struct udf_inode_info *iinfo;
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
85
  	uint32_t pos;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

48d6d8ff7   Marcin Slusarz   udf: cache struct...
87
  	iinfo = UDF_I(inode);
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
88
89
90
  	pos = udf_block_map(inode, 0);
  
  	down_read(&iinfo->i_data_sem);
48d6d8ff7   Marcin Slusarz   udf: cache struct...
91
92
  	if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
  		symlink = iinfo->i_ext.i_data + iinfo->i_lenEAttr;
28de7948a   Cyrill Gorcunov   UDF: coding style...
93
  	} else {
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
94
  		bh = sb_bread(inode->i_sb, pos);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
99
100
101
102
  
  		if (!bh)
  			goto out;
  
  		symlink = bh->b_data;
  	}
  
  	udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
3bf25cb40   Jan Kara   udf: use get_bh()
103
  	brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
104

4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
105
  	up_read(&iinfo->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
109
  	SetPageUptodate(page);
  	kunmap(page);
  	unlock_page(page);
  	return 0;
28de7948a   Cyrill Gorcunov   UDF: coding style...
110
111
  
  out:
4d0fb621d   Alessio Igor Bogani   udf: Replace bkl ...
112
  	up_read(&iinfo->i_data_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
119
120
121
  	SetPageError(page);
  	kunmap(page);
  	unlock_page(page);
  	return err;
  }
  
  /*
   * symlinks can't do much...
   */
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
122
  const struct address_space_operations udf_symlink_aops = {
28de7948a   Cyrill Gorcunov   UDF: coding style...
123
  	.readpage		= udf_symlink_filler,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
  };