Blame view

fs/isofs/namei.c 4.26 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   *  linux/fs/isofs/namei.c
   *
   *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
   *
   *  (C) 1991  Linus Torvalds - minix filesystem
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/gfp.h>
94f2f7157   Al Viro   [PATCH] isofs inc...
9
  #include "isofs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
16
  
  /*
   * ok, we cannot use strncmp, as the name is not in our data space.
   * Thus we'll have to use isofs_match. No big problem. Match also makes
   * some sanity tests.
   */
  static int
c3ed85a36   Dave Jones   isofs: fix up Cod...
17
  isofs_cmp(struct dentry *dentry, const char *compare, int dlen)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  {
  	struct qstr qstr;
  
  	if (!compare)
  		return 1;
  
  	/* check special "." and ".." files */
  	if (dlen == 1) {
  		/* "." */
  		if (compare[0] == 0) {
  			if (!dentry->d_name.len)
  				return 0;
  			compare = ".";
  		} else if (compare[0] == 1) {
  			compare = "..";
  			dlen = 2;
  		}
  	}
  
  	qstr.name = compare;
  	qstr.len = dlen;
621e155a3   Nick Piggin   fs: change d_comp...
39
40
  	return dentry->d_op->d_compare(NULL, NULL, NULL, NULL,
  			dentry->d_name.len, dentry->d_name.name, &qstr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
42
43
44
45
46
47
48
49
50
  }
  
  /*
   *	isofs_find_entry()
   *
   * finds an entry in the specified directory with the wanted name. It
   * returns the inode number of the found entry, or 0 on error.
   */
  static unsigned long
  isofs_find_entry(struct inode *dir, struct dentry *dentry,
c3ed85a36   Dave Jones   isofs: fix up Cod...
51
52
  	unsigned long *block_rv, unsigned long *offset_rv,
  	char *tmpname, struct iso_directory_record *tmpde)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
  {
  	unsigned long bufsize = ISOFS_BUFFER_SIZE(dir);
  	unsigned char bufbits = ISOFS_BUFFER_BITS(dir);
  	unsigned long block, f_pos, offset, block_saved, offset_saved;
c3ed85a36   Dave Jones   isofs: fix up Cod...
57
  	struct buffer_head *bh = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
59
60
61
  	struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb);
  
  	if (!ISOFS_I(dir)->i_first_extent)
  		return 0;
c3ed85a36   Dave Jones   isofs: fix up Cod...
62

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
67
  	f_pos = 0;
  	offset = 0;
  	block = 0;
  
  	while (f_pos < dir->i_size) {
c3ed85a36   Dave Jones   isofs: fix up Cod...
68
  		struct iso_directory_record *de;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  		int de_len, match, i, dlen;
  		char *dpnt;
  
  		if (!bh) {
  			bh = isofs_bread(dir, block);
  			if (!bh)
  				return 0;
  		}
  
  		de = (struct iso_directory_record *) (bh->b_data + offset);
  
  		de_len = *(unsigned char *) de;
  		if (!de_len) {
  			brelse(bh);
  			bh = NULL;
  			f_pos = (f_pos + ISOFS_BLOCK_SIZE) & ~(ISOFS_BLOCK_SIZE - 1);
  			block = f_pos >> bufbits;
  			offset = 0;
  			continue;
  		}
  
  		block_saved = bh->b_blocknr;
  		offset_saved = offset;
  		offset += de_len;
  		f_pos += de_len;
  
  		/* Make sure we have a full directory entry */
  		if (offset >= bufsize) {
  			int slop = bufsize - offset + de_len;
  			memcpy(tmpde, de, slop);
  			offset &= bufsize - 1;
  			block++;
  			brelse(bh);
  			bh = NULL;
  			if (offset) {
  				bh = isofs_bread(dir, block);
  				if (!bh)
  					return 0;
  				memcpy((void *) tmpde + slop, bh->b_data, offset);
  			}
  			de = tmpde;
  		}
  
  		dlen = de->name_len[0];
  		dpnt = de->name;
2deb1acc6   Jan Kara   isofs: fix access...
114
115
116
117
118
119
120
121
  		/* Basic sanity check, whether name doesn't exceed dir entry */
  		if (de_len < dlen + sizeof(struct iso_directory_record)) {
  			printk(KERN_NOTICE "iso9660: Corrupted directory entry"
  			       " in block %lu of inode %lu
  ", block,
  			       dir->i_ino);
  			return 0;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
  
  		if (sbi->s_rock &&
  		    ((i = get_rock_ridge_filename(de, tmpname, dir)))) {
c3ed85a36   Dave Jones   isofs: fix up Cod...
125
  			dlen = i;	/* possibly -1 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
  			dpnt = tmpname;
  #ifdef CONFIG_JOLIET
  		} else if (sbi->s_joliet_level) {
  			dlen = get_joliet_filename(de, tmpname, dir);
  			dpnt = tmpname;
  #endif
  		} else if (sbi->s_mapping == 'a') {
  			dlen = get_acorn_filename(de, tmpname, dir);
  			dpnt = tmpname;
  		} else if (sbi->s_mapping == 'n') {
  			dlen = isofs_name_translate(de, tmpname, dir);
  			dpnt = tmpname;
  		}
  
  		/*
9769f4eb3   Jeremy White   [PATCH] isofs: sh...
141
142
  		 * Skip hidden or associated files unless hide or showassoc,
  		 * respectively, is set
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
144
145
  		 */
  		match = 0;
  		if (dlen > 0 &&
5404ac8e4   Jan Kara   isofs: cleanup mo...
146
  			(!sbi->s_hide ||
9769f4eb3   Jeremy White   [PATCH] isofs: sh...
147
  				(!(de->flags[-sbi->s_high_sierra] & 1))) &&
5404ac8e4   Jan Kara   isofs: cleanup mo...
148
  			(sbi->s_showassoc ||
9769f4eb3   Jeremy White   [PATCH] isofs: sh...
149
150
  				(!(de->flags[-sbi->s_high_sierra] & 4)))) {
  			match = (isofs_cmp(dentry, dpnt, dlen) == 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
155
  		}
  		if (match) {
  			isofs_normalize_block_and_offset(de,
  							 &block_saved,
  							 &offset_saved);
c3ed85a36   Dave Jones   isofs: fix up Cod...
156
157
  			*block_rv = block_saved;
  			*offset_rv = offset_saved;
9769f4eb3   Jeremy White   [PATCH] isofs: sh...
158
  			brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
  			return 1;
  		}
  	}
9769f4eb3   Jeremy White   [PATCH] isofs: sh...
162
  	brelse(bh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
  	return 0;
  }
c3ed85a36   Dave Jones   isofs: fix up Cod...
165
  struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
  {
  	int found;
cd215237d   Borislav Petkov   fs/isofs/namei.c:...
168
169
  	unsigned long uninitialized_var(block);
  	unsigned long uninitialized_var(offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
  	struct inode *inode;
  	struct page *page;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
  	page = alloc_page(GFP_USER);
  	if (!page)
  		return ERR_PTR(-ENOMEM);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  	found = isofs_find_entry(dir, dentry,
c3ed85a36   Dave Jones   isofs: fix up Cod...
176
177
178
  				&block, &offset,
  				page_address(page),
  				1024 + page_address(page));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  	__free_page(page);
a9049376e   Al Viro   make d_splice_ali...
180
  	inode = found ? isofs_iget(dir->i_sb, block, offset) : NULL;
2ff6b1c25   Pekka Enberg   [PATCH] isofs: re...
181
  	return d_splice_alias(inode, dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
  }