Blame view

fs/hpfs/namei.c 15.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   *  linux/fs/hpfs/namei.c
   *
   *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
   *
   *  adding & removing files & directories
   */
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
8
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
  #include "hpfs_fn.h"
f49a26e77   Mikulas Patocka   hpfs: update ctim...
10
11
12
13
14
15
16
17
18
19
  static void hpfs_update_directory_times(struct inode *dir)
  {
  	time_t t = get_seconds();
  	if (t == dir->i_mtime.tv_sec &&
  	    t == dir->i_ctime.tv_sec)
  		return;
  	dir->i_mtime.tv_sec = dir->i_ctime.tv_sec = t;
  	dir->i_mtime.tv_nsec = dir->i_ctime.tv_nsec = 0;
  	hpfs_write_inode_nolock(dir);
  }
18bb1db3e   Al Viro   switch vfs_mkdir(...
20
  static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
21
  {
7e7742ee0   Al Viro   sanitize signedne...
22
  	const unsigned char *name = dentry->d_name.name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
28
29
30
31
32
33
34
  	unsigned len = dentry->d_name.len;
  	struct quad_buffer_head qbh0;
  	struct buffer_head *bh;
  	struct hpfs_dirent *de;
  	struct fnode *fnode;
  	struct dnode *dnode;
  	struct inode *result;
  	fnode_secno fno;
  	dnode_secno dno;
  	int r;
  	struct hpfs_dirent dee;
  	int err;
7e7742ee0   Al Viro   sanitize signedne...
35
  	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
36
  	hpfs_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
  	err = -ENOSPC;
  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
  	if (!fnode)
  		goto bail;
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
41
  	dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
  	if (!dnode)
  		goto bail1;
  	memset(&dee, 0, sizeof dee);
  	dee.directory = 1;
  	if (!(mode & 0222)) dee.read_only = 1;
  	/*dee.archive = 0;*/
  	dee.hidden = name[0] == '.';
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
49
50
  	dee.fnode = cpu_to_le32(fno);
  	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
  	result = new_inode(dir->i_sb);
  	if (!result)
  		goto bail2;
  	hpfs_init_inode(result);
  	result->i_ino = fno;
  	hpfs_i(result)->i_parent_dir = dir->i_ino;
  	hpfs_i(result)->i_dno = dno;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
58
  	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
60
61
62
63
64
65
66
67
  	result->i_ctime.tv_nsec = 0; 
  	result->i_mtime.tv_nsec = 0; 
  	result->i_atime.tv_nsec = 0; 
  	hpfs_i(result)->i_ea_size = 0;
  	result->i_mode |= S_IFDIR;
  	result->i_op = &hpfs_dir_iops;
  	result->i_fop = &hpfs_dir_ops;
  	result->i_blocks = 4;
  	result->i_size = 2048;
bfe868486   Miklos Szeredi   filesystems: add ...
68
  	set_nlink(result, 2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  	if (dee.read_only)
  		result->i_mode &= ~0222;
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
71
  	r = hpfs_add_dirent(dir, name, len, &dee);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
  	if (r == 1)
  		goto bail3;
  	if (r == -1) {
  		err = -EEXIST;
  		goto bail3;
  	}
  	fnode->len = len;
  	memcpy(fnode->name, name, len > 15 ? 15 : len);
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
80
  	fnode->up = cpu_to_le32(dir->i_ino);
c4c995430   Al Viro   hpfs: get rid of ...
81
  	fnode->flags |= FNODE_dir;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	fnode->btree.n_free_nodes = 7;
  	fnode->btree.n_used_nodes = 1;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
84
85
86
  	fnode->btree.first_free = cpu_to_le16(0x14);
  	fnode->u.external[0].disk_secno = cpu_to_le32(dno);
  	fnode->u.external[0].file_secno = cpu_to_le32(-1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  	dnode->root_dnode = 1;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
88
  	dnode->up = cpu_to_le32(fno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
90
  	de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
  	if (!(mode & 0222)) de->read_only = 1;
  	de->first = de->directory = 1;
  	/*de->hidden = de->system = 0;*/
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
94
  	de->fnode = cpu_to_le32(fno);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
95
96
97
98
  	mark_buffer_dirty(bh);
  	brelse(bh);
  	hpfs_mark_4buffers_dirty(&qbh0);
  	hpfs_brelse4(&qbh0);
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
99
  	inc_nlink(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  	insert_inode_hash(result);
0e1a43c71   Eric W. Biederman   userns: Convert h...
101
102
  	if (!uid_eq(result->i_uid, current_fsuid()) ||
  	    !gid_eq(result->i_gid, current_fsgid()) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  	    result->i_mode != (mode | S_IFDIR)) {
de395b8ac   David Howells   CRED: Wrap task c...
104
105
  		result->i_uid = current_fsuid();
  		result->i_gid = current_fsgid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
108
  		result->i_mode = mode | S_IFDIR;
  		hpfs_write_inode_nolock(result);
  	}
f49a26e77   Mikulas Patocka   hpfs: update ctim...
109
  	hpfs_update_directory_times(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  	d_instantiate(dentry, result);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
111
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
  	return 0;
  bail3:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
114
115
116
117
118
119
120
121
  	iput(result);
  bail2:
  	hpfs_brelse4(&qbh0);
  	hpfs_free_dnode(dir->i_sb, dno);
  bail1:
  	brelse(bh);
  	hpfs_free_sectors(dir->i_sb, fno, 1);
  bail:
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
122
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
  	return err;
  }
ebfc3b49a   Al Viro   don't pass nameid...
125
  static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
  {
7e7742ee0   Al Viro   sanitize signedne...
127
  	const unsigned char *name = dentry->d_name.name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
  	unsigned len = dentry->d_name.len;
  	struct inode *result = NULL;
  	struct buffer_head *bh;
  	struct fnode *fnode;
  	fnode_secno fno;
  	int r;
  	struct hpfs_dirent dee;
  	int err;
7e7742ee0   Al Viro   sanitize signedne...
136
  	if ((err = hpfs_chk_name(name, &len)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  		return err==-ENOENT ? -EINVAL : err;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
138
  	hpfs_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
146
  	err = -ENOSPC;
  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
  	if (!fnode)
  		goto bail;
  	memset(&dee, 0, sizeof dee);
  	if (!(mode & 0222)) dee.read_only = 1;
  	dee.archive = 1;
  	dee.hidden = name[0] == '.';
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
147
148
  	dee.fnode = cpu_to_le32(fno);
  	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
151
152
153
154
155
156
157
158
159
  
  	result = new_inode(dir->i_sb);
  	if (!result)
  		goto bail1;
  	
  	hpfs_init_inode(result);
  	result->i_ino = fno;
  	result->i_mode |= S_IFREG;
  	result->i_mode &= ~0111;
  	result->i_op = &hpfs_file_iops;
  	result->i_fop = &hpfs_file_ops;
bfe868486   Miklos Szeredi   filesystems: add ...
160
  	set_nlink(result, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
161
  	hpfs_i(result)->i_parent_dir = dir->i_ino;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
162
  	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
164
165
166
167
168
169
170
171
172
  	result->i_ctime.tv_nsec = 0;
  	result->i_mtime.tv_nsec = 0;
  	result->i_atime.tv_nsec = 0;
  	hpfs_i(result)->i_ea_size = 0;
  	if (dee.read_only)
  		result->i_mode &= ~0222;
  	result->i_blocks = 1;
  	result->i_size = 0;
  	result->i_data.a_ops = &hpfs_aops;
  	hpfs_i(result)->mmu_private = 0;
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
173
  	r = hpfs_add_dirent(dir, name, len, &dee);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
174
175
176
177
178
179
180
181
  	if (r == 1)
  		goto bail2;
  	if (r == -1) {
  		err = -EEXIST;
  		goto bail2;
  	}
  	fnode->len = len;
  	memcpy(fnode->name, name, len > 15 ? 15 : len);
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
182
  	fnode->up = cpu_to_le32(dir->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
  	mark_buffer_dirty(bh);
  	brelse(bh);
  
  	insert_inode_hash(result);
0e1a43c71   Eric W. Biederman   userns: Convert h...
187
188
  	if (!uid_eq(result->i_uid, current_fsuid()) ||
  	    !gid_eq(result->i_gid, current_fsgid()) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
  	    result->i_mode != (mode | S_IFREG)) {
de395b8ac   David Howells   CRED: Wrap task c...
190
191
  		result->i_uid = current_fsuid();
  		result->i_gid = current_fsgid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
  		result->i_mode = mode | S_IFREG;
  		hpfs_write_inode_nolock(result);
  	}
f49a26e77   Mikulas Patocka   hpfs: update ctim...
195
  	hpfs_update_directory_times(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  	d_instantiate(dentry, result);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
197
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198
199
200
  	return 0;
  
  bail2:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
202
203
204
205
  	iput(result);
  bail1:
  	brelse(bh);
  	hpfs_free_sectors(dir->i_sb, fno, 1);
  bail:
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
206
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
208
  	return err;
  }
1a67aafb5   Al Viro   switch ->mknod() ...
209
  static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
  {
7e7742ee0   Al Viro   sanitize signedne...
211
  	const unsigned char *name = dentry->d_name.name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
215
216
217
218
219
  	unsigned len = dentry->d_name.len;
  	struct buffer_head *bh;
  	struct fnode *fnode;
  	fnode_secno fno;
  	int r;
  	struct hpfs_dirent dee;
  	struct inode *result = NULL;
  	int err;
7e7742ee0   Al Viro   sanitize signedne...
220
  	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  	if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
222
  	hpfs_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
228
229
230
  	err = -ENOSPC;
  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
  	if (!fnode)
  		goto bail;
  	memset(&dee, 0, sizeof dee);
  	if (!(mode & 0222)) dee.read_only = 1;
  	dee.archive = 1;
  	dee.hidden = name[0] == '.';
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
231
232
  	dee.fnode = cpu_to_le32(fno);
  	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
236
237
238
239
240
  
  	result = new_inode(dir->i_sb);
  	if (!result)
  		goto bail1;
  
  	hpfs_init_inode(result);
  	result->i_ino = fno;
  	hpfs_i(result)->i_parent_dir = dir->i_ino;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
241
  	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
  	result->i_ctime.tv_nsec = 0;
  	result->i_mtime.tv_nsec = 0;
  	result->i_atime.tv_nsec = 0;
  	hpfs_i(result)->i_ea_size = 0;
de395b8ac   David Howells   CRED: Wrap task c...
246
247
  	result->i_uid = current_fsuid();
  	result->i_gid = current_fsgid();
bfe868486   Miklos Szeredi   filesystems: add ...
248
  	set_nlink(result, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
250
251
  	result->i_size = 0;
  	result->i_blocks = 1;
  	init_special_inode(result, mode, rdev);
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
252
  	r = hpfs_add_dirent(dir, name, len, &dee);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
257
258
259
260
  	if (r == 1)
  		goto bail2;
  	if (r == -1) {
  		err = -EEXIST;
  		goto bail2;
  	}
  	fnode->len = len;
  	memcpy(fnode->name, name, len > 15 ? 15 : len);
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
261
  	fnode->up = cpu_to_le32(dir->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
266
  	mark_buffer_dirty(bh);
  
  	insert_inode_hash(result);
  
  	hpfs_write_inode_nolock(result);
f49a26e77   Mikulas Patocka   hpfs: update ctim...
267
  	hpfs_update_directory_times(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
  	d_instantiate(dentry, result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
  	brelse(bh);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
270
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
  	return 0;
  bail2:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
274
275
276
277
  	iput(result);
  bail1:
  	brelse(bh);
  	hpfs_free_sectors(dir->i_sb, fno, 1);
  bail:
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
278
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
280
281
282
283
  	return err;
  }
  
  static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
  {
7e7742ee0   Al Viro   sanitize signedne...
284
  	const unsigned char *name = dentry->d_name.name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
291
292
  	unsigned len = dentry->d_name.len;
  	struct buffer_head *bh;
  	struct fnode *fnode;
  	fnode_secno fno;
  	int r;
  	struct hpfs_dirent dee;
  	struct inode *result;
  	int err;
7e7742ee0   Al Viro   sanitize signedne...
293
  	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
294
  	hpfs_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  	if (hpfs_sb(dir->i_sb)->sb_eas < 2) {
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
296
  		hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
297
298
299
300
301
302
303
304
305
  		return -EPERM;
  	}
  	err = -ENOSPC;
  	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
  	if (!fnode)
  		goto bail;
  	memset(&dee, 0, sizeof dee);
  	dee.archive = 1;
  	dee.hidden = name[0] == '.';
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
306
307
  	dee.fnode = cpu_to_le32(fno);
  	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
309
310
311
312
313
314
  
  	result = new_inode(dir->i_sb);
  	if (!result)
  		goto bail1;
  	result->i_ino = fno;
  	hpfs_init_inode(result);
  	hpfs_i(result)->i_parent_dir = dir->i_ino;
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
315
  	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
  	result->i_ctime.tv_nsec = 0;
  	result->i_mtime.tv_nsec = 0;
  	result->i_atime.tv_nsec = 0;
  	hpfs_i(result)->i_ea_size = 0;
  	result->i_mode = S_IFLNK | 0777;
de395b8ac   David Howells   CRED: Wrap task c...
321
322
  	result->i_uid = current_fsuid();
  	result->i_gid = current_fsgid();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	result->i_blocks = 1;
bfe868486   Miklos Szeredi   filesystems: add ...
324
  	set_nlink(result, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	result->i_size = strlen(symlink);
21fc61c73   Al Viro   don't put symlink...
326
  	inode_nohighmem(result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
  	result->i_op = &page_symlink_inode_operations;
  	result->i_data.a_ops = &hpfs_symlink_aops;
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
329
  	r = hpfs_add_dirent(dir, name, len, &dee);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
330
331
332
333
334
335
336
337
  	if (r == 1)
  		goto bail2;
  	if (r == -1) {
  		err = -EEXIST;
  		goto bail2;
  	}
  	fnode->len = len;
  	memcpy(fnode->name, name, len > 15 ? 15 : len);
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
338
  	fnode->up = cpu_to_le32(dir->i_ino);
7e7742ee0   Al Viro   sanitize signedne...
339
  	hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
344
345
  	mark_buffer_dirty(bh);
  	brelse(bh);
  
  	insert_inode_hash(result);
  
  	hpfs_write_inode_nolock(result);
f49a26e77   Mikulas Patocka   hpfs: update ctim...
346
  	hpfs_update_directory_times(dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  	d_instantiate(dentry, result);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
348
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
350
  	return 0;
  bail2:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
352
353
354
355
  	iput(result);
  bail1:
  	brelse(bh);
  	hpfs_free_sectors(dir->i_sb, fno, 1);
  bail:
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
356
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
358
359
360
361
  	return err;
  }
  
  static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
  {
7e7742ee0   Al Viro   sanitize signedne...
362
  	const unsigned char *name = dentry->d_name.name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
364
365
  	unsigned len = dentry->d_name.len;
  	struct quad_buffer_head qbh;
  	struct hpfs_dirent *de;
2b0143b5c   David Howells   VFS: normal files...
366
  	struct inode *inode = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  	dnode_secno dno;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
  	int r;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  	int err;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
370
  	hpfs_lock(dir->i_sb);
7e7742ee0   Al Viro   sanitize signedne...
371
  	hpfs_adjust_length(name, &len);
b6853f78e   Mikulas Patocka   hpfs: don't trunc...
372

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
373
  	err = -ENOENT;
7e7742ee0   Al Viro   sanitize signedne...
374
  	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
380
381
382
383
384
  	if (!de)
  		goto out;
  
  	err = -EPERM;
  	if (de->first)
  		goto out1;
  
  	err = -EISDIR;
  	if (de->directory)
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
386
387
388
389
390
  	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
  	switch (r) {
  	case 1:
  		hpfs_error(dir->i_sb, "there was error when removing dirent");
  		err = -EFSERROR;
  		break;
b6853f78e   Mikulas Patocka   hpfs: don't trunc...
391
  	case 2:		/* no space for deleting */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
  		err = -ENOSPC;
b6853f78e   Mikulas Patocka   hpfs: don't trunc...
393
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394
  	default:
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
395
  		drop_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
400
401
402
  		err = 0;
  	}
  	goto out;
  
  out1:
  	hpfs_brelse4(&qbh);
  out:
f49a26e77   Mikulas Patocka   hpfs: update ctim...
403
404
  	if (!err)
  		hpfs_update_directory_times(dir);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
405
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
408
409
410
  	return err;
  }
  
  static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
  {
7e7742ee0   Al Viro   sanitize signedne...
411
  	const unsigned char *name = dentry->d_name.name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
414
  	unsigned len = dentry->d_name.len;
  	struct quad_buffer_head qbh;
  	struct hpfs_dirent *de;
2b0143b5c   David Howells   VFS: normal files...
415
  	struct inode *inode = d_inode(dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
  	dnode_secno dno;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
419
  	int n_items = 0;
  	int err;
  	int r;
7e7742ee0   Al Viro   sanitize signedne...
420
  	hpfs_adjust_length(name, &len);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
421
  	hpfs_lock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  	err = -ENOENT;
7e7742ee0   Al Viro   sanitize signedne...
423
  	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
  	if (!de)
  		goto out;
  
  	err = -EPERM;
  	if (de->first)
  		goto out1;
  
  	err = -ENOTDIR;
  	if (!de->directory)
  		goto out1;
  
  	hpfs_count_dnodes(dir->i_sb, hpfs_i(inode)->i_dno, NULL, NULL, &n_items);
  	err = -ENOTEMPTY;
  	if (n_items)
  		goto out1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
440
441
442
443
444
445
446
447
448
  	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
  	switch (r) {
  	case 1:
  		hpfs_error(dir->i_sb, "there was error when removing dirent");
  		err = -EFSERROR;
  		break;
  	case 2:
  		err = -ENOSPC;
  		break;
  	default:
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
449
  		drop_nlink(dir);
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
450
  		clear_nlink(inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451
452
453
454
455
456
  		err = 0;
  	}
  	goto out;
  out1:
  	hpfs_brelse4(&qbh);
  out:
f49a26e77   Mikulas Patocka   hpfs: update ctim...
457
458
  	if (!err)
  		hpfs_update_directory_times(dir);
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
459
  	hpfs_unlock(dir->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
461
462
463
464
  	return err;
  }
  
  static int hpfs_symlink_readpage(struct file *file, struct page *page)
  {
21fc61c73   Al Viro   don't put symlink...
465
  	char *link = page_address(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
467
468
469
470
471
  	struct inode *i = page->mapping->host;
  	struct fnode *fnode;
  	struct buffer_head *bh;
  	int err;
  
  	err = -EIO;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
472
  	hpfs_lock(i->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
473
474
475
476
477
478
  	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
  		goto fail;
  	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
  	brelse(bh);
  	if (err)
  		goto fail;
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
479
  	hpfs_unlock(i->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
480
  	SetPageUptodate(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
  	unlock_page(page);
  	return 0;
  
  fail:
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
485
  	hpfs_unlock(i->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
  	SetPageError(page);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
  	unlock_page(page);
  	return err;
  }
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
490
  const struct address_space_operations hpfs_symlink_aops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
492
493
494
495
496
  	.readpage	= hpfs_symlink_readpage
  };
  	
  static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
  		struct inode *new_dir, struct dentry *new_dentry)
  {
7e7742ee0   Al Viro   sanitize signedne...
497
498
499
500
  	const unsigned char *old_name = old_dentry->d_name.name;
  	unsigned old_len = old_dentry->d_name.len;
  	const unsigned char *new_name = new_dentry->d_name.name;
  	unsigned new_len = new_dentry->d_name.len;
2b0143b5c   David Howells   VFS: normal files...
501
502
  	struct inode *i = d_inode(old_dentry);
  	struct inode *new_inode = d_inode(new_dentry);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
507
508
509
510
  	struct quad_buffer_head qbh, qbh1;
  	struct hpfs_dirent *dep, *nde;
  	struct hpfs_dirent de;
  	dnode_secno dno;
  	int r;
  	struct buffer_head *bh;
  	struct fnode *fnode;
  	int err;
e4eaac06b   Sage Weil   vfs: push dentry_...
511

7e7742ee0   Al Viro   sanitize signedne...
512
  	if ((err = hpfs_chk_name(new_name, &new_len))) return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513
  	err = 0;
7e7742ee0   Al Viro   sanitize signedne...
514
  	hpfs_adjust_length(old_name, &old_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
515

9a311b96c   Arnd Bergmann   hpfs: remove the BKL
516
  	hpfs_lock(i->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
517
  	/* order doesn't matter, due to VFS exclusion */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
519
520
521
522
523
  	
  	/* Erm? Moving over the empty non-busy directory is perfectly legal */
  	if (new_inode && S_ISDIR(new_inode->i_mode)) {
  		err = -EINVAL;
  		goto end1;
  	}
7e7742ee0   Al Viro   sanitize signedne...
524
  	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
527
528
529
530
531
532
533
534
  		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
  		err = -ENOENT;
  		goto end1;
  	}
  	copy_de(&de, dep);
  	de.hidden = new_name[0] == '.';
  
  	if (new_inode) {
  		int r;
  		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
7e7742ee0   Al Viro   sanitize signedne...
535
  			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) {
ce71ec368   Dave Hansen   [PATCH] r/o bind ...
536
  				clear_nlink(new_inode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
  				copy_de(nde, &de);
  				memcpy(nde->name, new_name, new_len);
  				hpfs_mark_4buffers_dirty(&qbh1);
  				hpfs_brelse4(&qbh1);
  				goto end;
  			}
  			hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
  			err = -EFSERROR;
  			goto end1;
  		}
  		err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
  		goto end1;
  	}
  
  	if (new_dir == old_dir) hpfs_brelse4(&qbh);
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
552
  	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
553
554
555
556
557
558
559
  		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
  		err = r == 1 ? -ENOSPC : -EFSERROR;
  		if (new_dir != old_dir) hpfs_brelse4(&qbh);
  		goto end1;
  	}
  	
  	if (new_dir == old_dir)
7e7742ee0   Al Viro   sanitize signedne...
560
  		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
561
562
563
564
565
566
  			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
  			err = -ENOENT;
  			goto end1;
  		}
  
  	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
  		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
  		err = r == 2 ? -ENOSPC : -EFSERROR;
  		goto end1;
  	}
7d23ce36e   Mikulas Patocka   HPFS: Remove rema...
571

f49a26e77   Mikulas Patocka   hpfs: update ctim...
572
  end:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
573
574
  	hpfs_i(i)->i_parent_dir = new_dir->i_ino;
  	if (S_ISDIR(i->i_mode)) {
d8c76e6f4   Dave Hansen   [PATCH] r/o bind ...
575
  		inc_nlink(new_dir);
9a53c3a78   Dave Hansen   [PATCH] r/o bind ...
576
  		drop_nlink(old_dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  	}
  	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
0b69760be   Mikulas Patocka   HPFS: Fix endiani...
579
  		fnode->up = cpu_to_le32(new_dir->i_ino);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580
581
582
583
584
585
  		fnode->len = new_len;
  		memcpy(fnode->name, new_name, new_len>15?15:new_len);
  		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
  		mark_buffer_dirty(bh);
  		brelse(bh);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  end1:
f49a26e77   Mikulas Patocka   hpfs: update ctim...
587
588
589
590
  	if (!err) {
  		hpfs_update_directory_times(old_dir);
  		hpfs_update_directory_times(new_dir);
  	}
9a311b96c   Arnd Bergmann   hpfs: remove the BKL
591
  	hpfs_unlock(i->i_sb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
592
593
  	return err;
  }
92e1d5be9   Arjan van de Ven   [PATCH] mark stru...
594
  const struct inode_operations hpfs_dir_iops =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
596
597
598
599
600
601
602
603
  {
  	.create		= hpfs_create,
  	.lookup		= hpfs_lookup,
  	.unlink		= hpfs_unlink,
  	.symlink	= hpfs_symlink,
  	.mkdir		= hpfs_mkdir,
  	.rmdir		= hpfs_rmdir,
  	.mknod		= hpfs_mknod,
  	.rename		= hpfs_rename,
ca30bc995   Christoph Hellwig   [PATCH] hpfs: cle...
604
  	.setattr	= hpfs_setattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
  };