1 /*
2  *  linux/fs/hpfs/namei.c
3  *
4  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
5  *
6  *  adding & removing files & directories
7  */
8 
9 #include <linux/string.h>
10 #include "hpfs_fn.h"
11 
hpfs_mkdir(struct inode * dir,struct dentry * dentry,int mode)12 int hpfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
13 {
14 	const char *name = dentry->d_name.name;
15 	unsigned len = dentry->d_name.len;
16 	struct quad_buffer_head qbh0;
17 	struct buffer_head *bh;
18 	struct hpfs_dirent *de;
19 	struct fnode *fnode;
20 	struct dnode *dnode;
21 	struct inode *result;
22 	fnode_secno fno;
23 	dnode_secno dno;
24 	int r;
25 	struct hpfs_dirent dee;
26 	int err;
27 	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
28 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
29 	if (!(dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0, 1))) goto bail1;
30 	memset(&dee, 0, sizeof dee);
31 	dee.directory = 1;
32 	if (!(mode & 0222)) dee.read_only = 1;
33 	/*dee.archive = 0;*/
34 	dee.hidden = name[0] == '.';
35 	dee.fnode = fno;
36 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
37 	hpfs_lock_inode(dir);
38 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
39 	if (r == 1) goto bail2;
40 	if (r == -1) {
41 		brelse(bh);
42 		hpfs_brelse4(&qbh0);
43 		hpfs_free_sectors(dir->i_sb, fno, 1);
44 		hpfs_free_dnode(dir->i_sb, dno);
45 		hpfs_unlock_inode(dir);
46 		return -EEXIST;
47 	}
48 	fnode->len = len;
49 	memcpy(fnode->name, name, len > 15 ? 15 : len);
50 	fnode->up = dir->i_ino;
51 	fnode->dirflag = 1;
52 	fnode->btree.n_free_nodes = 7;
53 	fnode->btree.n_used_nodes = 1;
54 	fnode->btree.first_free = 0x14;
55 	fnode->u.external[0].disk_secno = dno;
56 	fnode->u.external[0].file_secno = -1;
57 	dnode->root_dnode = 1;
58 	dnode->up = fno;
59 	de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
60 	de->creation_date = de->write_date = de->read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
61 	if (!(mode & 0222)) de->read_only = 1;
62 	de->first = de->directory = 1;
63 	/*de->hidden = de->system = 0;*/
64 	de->fnode = fno;
65 	mark_buffer_dirty(bh);
66 	brelse(bh);
67 	hpfs_mark_4buffers_dirty(&qbh0);
68 	hpfs_brelse4(&qbh0);
69 	dir->i_nlink++;
70 	hpfs_lock_iget(dir->i_sb, 1);
71 	if ((result = iget(dir->i_sb, fno))) {
72 		result->i_hpfs_parent_dir = dir->i_ino;
73 		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
74 		result->i_hpfs_ea_size = 0;
75 		if (dee.read_only) result->i_mode &= ~0222;
76 		if (result->i_uid != current->fsuid ||
77 		    result->i_gid != current->fsgid ||
78 		    result->i_mode != (mode | S_IFDIR)) {
79 			result->i_uid = current->fsuid;
80 			result->i_gid = current->fsgid;
81 			result->i_mode = mode | S_IFDIR;
82 			hpfs_write_inode_nolock(result);
83 		}
84 		d_instantiate(dentry, result);
85 	}
86 	hpfs_unlock_iget(dir->i_sb);
87 	hpfs_unlock_inode(dir);
88 	return 0;
89 	bail2:
90 	hpfs_brelse4(&qbh0);
91 	hpfs_free_dnode(dir->i_sb, dno);
92 	hpfs_unlock_inode(dir);
93 	bail1:
94 	brelse(bh);
95 	hpfs_free_sectors(dir->i_sb, fno, 1);
96 	bail:
97 	return -ENOSPC;
98 }
99 
hpfs_create(struct inode * dir,struct dentry * dentry,int mode)100 int hpfs_create(struct inode *dir, struct dentry *dentry, int mode)
101 {
102 	const char *name = dentry->d_name.name;
103 	unsigned len = dentry->d_name.len;
104 	struct inode *result = NULL;
105 	struct buffer_head *bh;
106 	struct fnode *fnode;
107 	fnode_secno fno;
108 	int r;
109 	struct hpfs_dirent dee;
110 	int err;
111 	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
112 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
113 	memset(&dee, 0, sizeof dee);
114 	if (!(mode & 0222)) dee.read_only = 1;
115 	dee.archive = 1;
116 	dee.hidden = name[0] == '.';
117 	dee.fnode = fno;
118 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
119 	hpfs_lock_inode(dir);
120 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
121 	if (r == 1) goto bail1;
122 	if (r == -1) {
123 		brelse(bh);
124 		hpfs_free_sectors(dir->i_sb, fno, 1);
125 		hpfs_unlock_inode(dir);
126 		return -EEXIST;
127 	}
128 	fnode->len = len;
129 	memcpy(fnode->name, name, len > 15 ? 15 : len);
130 	fnode->up = dir->i_ino;
131 	mark_buffer_dirty(bh);
132 	brelse(bh);
133 	hpfs_lock_iget(dir->i_sb, 2);
134 	if ((result = iget(dir->i_sb, fno))) {
135 		hpfs_decide_conv(result, (char *)name, len);
136 		result->i_hpfs_parent_dir = dir->i_ino;
137 		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
138 		result->i_hpfs_ea_size = 0;
139 		if (dee.read_only) result->i_mode &= ~0222;
140 		if (result->i_blocks == -1) result->i_blocks = 1;
141 		if (result->i_size == -1) {
142 			result->i_size = 0;
143 			result->i_data.a_ops = &hpfs_aops;
144 			result->u.hpfs_i.mmu_private = 0;
145 		}
146 		if (result->i_uid != current->fsuid ||
147 		    result->i_gid != current->fsgid ||
148 		    result->i_mode != (mode | S_IFREG)) {
149 			result->i_uid = current->fsuid;
150 			result->i_gid = current->fsgid;
151 			result->i_mode = mode | S_IFREG;
152 			hpfs_write_inode_nolock(result);
153 		}
154 		d_instantiate(dentry, result);
155 	}
156 	hpfs_unlock_iget(dir->i_sb);
157 	hpfs_unlock_inode(dir);
158 	return 0;
159 	bail1:
160 	brelse(bh);
161 	hpfs_free_sectors(dir->i_sb, fno, 1);
162 	hpfs_unlock_inode(dir);
163 	bail:
164 	return -ENOSPC;
165 }
166 
hpfs_mknod(struct inode * dir,struct dentry * dentry,int mode,int rdev)167 int hpfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
168 {
169 	const char *name = dentry->d_name.name;
170 	unsigned len = dentry->d_name.len;
171 	struct buffer_head *bh;
172 	struct fnode *fnode;
173 	fnode_secno fno;
174 	int r;
175 	struct hpfs_dirent dee;
176 	struct inode *result = NULL;
177 	int err;
178 	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
179 	if (dir->i_sb->s_hpfs_eas < 2) return -EPERM;
180 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
181 	memset(&dee, 0, sizeof dee);
182 	if (!(mode & 0222)) dee.read_only = 1;
183 	dee.archive = 1;
184 	dee.hidden = name[0] == '.';
185 	dee.fnode = fno;
186 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
187 	hpfs_lock_inode(dir);
188 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
189 	if (r == 1) goto bail1;
190 	if (r == -1) {
191 		brelse(bh);
192 		hpfs_free_sectors(dir->i_sb, fno, 1);
193 		hpfs_unlock_inode(dir);
194 		return -EEXIST;
195 	}
196 	fnode->len = len;
197 	memcpy(fnode->name, name, len > 15 ? 15 : len);
198 	fnode->up = dir->i_ino;
199 	mark_buffer_dirty(bh);
200 	hpfs_lock_iget(dir->i_sb, 2);
201 	if ((result = iget(dir->i_sb, fno))) {
202 		result->i_hpfs_parent_dir = dir->i_ino;
203 		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
204 		result->i_hpfs_ea_size = 0;
205 		/*if (result->i_blocks == -1) result->i_blocks = 1;
206 		if (result->i_size == -1) result->i_size = 0;*/
207 		result->i_uid = current->fsuid;
208 		result->i_gid = current->fsgid;
209 		result->i_nlink = 1;
210 		result->i_size = 0;
211 		result->i_blocks = 1;
212 		init_special_inode(result, mode, rdev);
213 		hpfs_write_inode_nolock(result);
214 		d_instantiate(dentry, result);
215 	}
216 	hpfs_unlock_iget(dir->i_sb);
217 	hpfs_unlock_inode(dir);
218 	brelse(bh);
219 	return 0;
220 	bail1:
221 	brelse(bh);
222 	hpfs_free_sectors(dir->i_sb, fno, 1);
223 	hpfs_unlock_inode(dir);
224 	bail:
225 	return -ENOSPC;
226 }
227 
228 extern struct address_space_operations hpfs_symlink_aops;
229 
hpfs_symlink(struct inode * dir,struct dentry * dentry,const char * symlink)230 int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
231 {
232 	const char *name = dentry->d_name.name;
233 	unsigned len = dentry->d_name.len;
234 	struct buffer_head *bh;
235 	struct fnode *fnode;
236 	fnode_secno fno;
237 	int r;
238 	struct hpfs_dirent dee;
239 	struct inode *result;
240 	int err;
241 	if ((err = hpfs_chk_name((char *)name, &len))) return err==-ENOENT ? -EINVAL : err;
242 	if (dir->i_sb->s_hpfs_eas < 2) return -EPERM;
243 	if (!(fnode = hpfs_alloc_fnode(dir->i_sb, dir->i_hpfs_dno, &fno, &bh))) goto bail;
244 	memset(&dee, 0, sizeof dee);
245 	dee.archive = 1;
246 	dee.hidden = name[0] == '.';
247 	dee.fnode = fno;
248 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, CURRENT_TIME);
249 	hpfs_lock_inode(dir);
250 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
251 	if (r == 1) goto bail1;
252 	if (r == -1) {
253 		brelse(bh);
254 		hpfs_free_sectors(dir->i_sb, fno, 1);
255 		hpfs_unlock_inode(dir);
256 		return -EEXIST;
257 	}
258 	fnode->len = len;
259 	memcpy(fnode->name, name, len > 15 ? 15 : len);
260 	fnode->up = dir->i_ino;
261 	mark_buffer_dirty(bh);
262 	brelse(bh);
263 	hpfs_lock_iget(dir->i_sb, 2);
264 	if ((result = iget(dir->i_sb, fno))) {
265 		result->i_hpfs_parent_dir = dir->i_ino;
266 		result->i_ctime = result->i_mtime = result->i_atime = local_to_gmt(dir->i_sb, dee.creation_date);
267 		result->i_hpfs_ea_size = 0;
268 		/*if (result->i_blocks == -1) result->i_blocks = 1;
269 		if (result->i_size == -1) result->i_size = 0;*/
270 		result->i_mode = S_IFLNK | 0777;
271 		result->i_uid = current->fsuid;
272 		result->i_gid = current->fsgid;
273 		result->i_blocks = 1;
274 		result->i_size = strlen(symlink);
275 		result->i_op = &page_symlink_inode_operations;
276 		result->i_data.a_ops = &hpfs_symlink_aops;
277 		if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) {
278 			hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
279 			mark_buffer_dirty(bh);
280 			brelse(bh);
281 		}
282 		hpfs_write_inode_nolock(result);
283 		d_instantiate(dentry, result);
284 	}
285 	hpfs_unlock_iget(dir->i_sb);
286 	hpfs_unlock_inode(dir);
287 	return 0;
288 	bail1:
289 	brelse(bh);
290 	hpfs_free_sectors(dir->i_sb, fno, 1);
291 	hpfs_unlock_inode(dir);
292 	bail:
293 	return -ENOSPC;
294 }
295 
hpfs_unlink(struct inode * dir,struct dentry * dentry)296 int hpfs_unlink(struct inode *dir, struct dentry *dentry)
297 {
298 	const char *name = dentry->d_name.name;
299 	unsigned len = dentry->d_name.len;
300 	struct quad_buffer_head qbh;
301 	struct hpfs_dirent *de;
302 	struct inode *inode = dentry->d_inode;
303 	dnode_secno dno;
304 	fnode_secno fno;
305 	int r;
306 	int rep = 0;
307 	hpfs_adjust_length((char *)name, &len);
308 	again:
309 	hpfs_lock_2inodes(dir, inode);
310 	if (!(de = map_dirent(dir, dir->i_hpfs_dno, (char *)name, len, &dno, &qbh))) {
311 		hpfs_unlock_2inodes(dir, inode);
312 		return -ENOENT;
313 	}
314 	if (de->first) {
315 		hpfs_brelse4(&qbh);
316 		hpfs_unlock_2inodes(dir, inode);
317 		return -EPERM;
318 	}
319 	if (de->directory) {
320 		hpfs_brelse4(&qbh);
321 		hpfs_unlock_2inodes(dir, inode);
322 		return -EISDIR;
323 	}
324 	fno = de->fnode;
325 	if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1) hpfs_error(dir->i_sb, "there was error when removing dirent");
326 	if (r != 2) {
327 		inode->i_nlink--;
328 		hpfs_unlock_2inodes(dir, inode);
329 	} else {	/* no space for deleting, try to truncate file */
330 		struct iattr newattrs;
331 		int err;
332 		hpfs_unlock_2inodes(dir, inode);
333 		if (rep)
334 			goto ret;
335 		d_drop(dentry);
336 		if (atomic_read(&dentry->d_count) > 1 ||
337 		    permission(inode, MAY_WRITE) ||
338 		    get_write_access(inode)) {
339 			d_rehash(dentry);
340 			goto ret;
341 		}
342 		/*printk("HPFS: truncating file before delete.\n");*/
343 		down(&inode->i_sem);
344 		newattrs.ia_size = 0;
345 		newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
346 		err = notify_change(dentry, &newattrs);
347 		up(&inode->i_sem);
348 		put_write_access(inode);
349 		if (err)
350 			goto ret;
351 		rep = 1;
352 		goto again;
353 	}
354 	ret:
355 	return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
356 }
357 
hpfs_rmdir(struct inode * dir,struct dentry * dentry)358 int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
359 {
360 	const char *name = dentry->d_name.name;
361 	unsigned len = dentry->d_name.len;
362 	struct quad_buffer_head qbh;
363 	struct hpfs_dirent *de;
364 	struct inode *inode = dentry->d_inode;
365 	dnode_secno dno;
366 	fnode_secno fno;
367 	int n_items = 0;
368 	int r;
369 	hpfs_adjust_length((char *)name, &len);
370 	hpfs_lock_2inodes(dir, inode);
371 	if (!(de = map_dirent(dir, dir->i_hpfs_dno, (char *)name, len, &dno, &qbh))) {
372 		hpfs_unlock_2inodes(dir, inode);
373 		return -ENOENT;
374 	}
375 	if (de->first) {
376 		hpfs_brelse4(&qbh);
377 		hpfs_unlock_2inodes(dir, inode);
378 		return -EPERM;
379 	}
380 	if (!de->directory) {
381 		hpfs_brelse4(&qbh);
382 		hpfs_unlock_2inodes(dir, inode);
383 		return -ENOTDIR;
384 	}
385 	hpfs_count_dnodes(dir->i_sb, inode->i_hpfs_dno, NULL, NULL, &n_items);
386 	if (n_items) {
387 		hpfs_brelse4(&qbh);
388 		hpfs_unlock_2inodes(dir, inode);
389 		return -ENOTEMPTY;
390 	}
391 	fno = de->fnode;
392 	if ((r = hpfs_remove_dirent(dir, dno, de, &qbh, 1)) == 1)
393 		hpfs_error(dir->i_sb, "there was error when removing dirent");
394 	if (r != 2) {
395 		dir->i_nlink--;
396 		inode->i_nlink = 0;
397 		hpfs_unlock_2inodes(dir, inode);
398 	} else hpfs_unlock_2inodes(dir, inode);
399 	return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
400 }
401 
hpfs_symlink_readpage(struct file * file,struct page * page)402 int hpfs_symlink_readpage(struct file *file, struct page *page)
403 {
404 	char *link = kmap(page);
405 	struct inode *i = page->mapping->host;
406 	struct fnode *fnode;
407 	struct buffer_head *bh;
408 	int err;
409 
410 	err = -EIO;
411 	lock_kernel();
412 	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
413 		goto fail;
414 	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
415 	brelse(bh);
416 	if (err)
417 		goto fail;
418 	unlock_kernel();
419 	SetPageUptodate(page);
420 	kunmap(page);
421 	UnlockPage(page);
422 	return 0;
423 
424 fail:
425 	unlock_kernel();
426 	SetPageError(page);
427 	kunmap(page);
428 	UnlockPage(page);
429 	return err;
430 }
431 
hpfs_rename(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry)432 int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
433 		struct inode *new_dir, struct dentry *new_dentry)
434 {
435 	char *old_name = (char *)old_dentry->d_name.name;
436 	int old_len = old_dentry->d_name.len;
437 	char *new_name = (char *)new_dentry->d_name.name;
438 	int new_len = new_dentry->d_name.len;
439 	struct inode *i = old_dentry->d_inode;
440 	struct inode *new_inode = new_dentry->d_inode;
441 	struct quad_buffer_head qbh, qbh1;
442 	struct hpfs_dirent *dep, *nde;
443 	struct hpfs_dirent de;
444 	dnode_secno dno;
445 	int r;
446 	struct buffer_head *bh;
447 	struct fnode *fnode;
448 	int err;
449 	if ((err = hpfs_chk_name((char *)new_name, &new_len))) return err;
450 	err = 0;
451 	hpfs_adjust_length((char *)old_name, &old_len);
452 
453 	hpfs_lock_3inodes(old_dir, new_dir, i);
454 
455 	/* Erm? Moving over the empty non-busy directory is perfectly legal */
456 	if (new_inode && S_ISDIR(new_inode->i_mode)) {
457 		err = -EINVAL;
458 		goto end1;
459 	}
460 
461 	if (!(dep = map_dirent(old_dir, old_dir->i_hpfs_dno, (char *)old_name, old_len, &dno, &qbh))) {
462 		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
463 		err = -ENOENT;
464 		goto end1;
465 	}
466 	copy_de(&de, dep);
467 	de.hidden = new_name[0] == '.';
468 
469 	if (new_inode) {
470 		int r;
471 		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
472 			if ((nde = map_dirent(new_dir, new_dir->i_hpfs_dno, (char *)new_name, new_len, NULL, &qbh1))) {
473 				new_inode->i_nlink = 0;
474 				copy_de(nde, &de);
475 				memcpy(nde->name, new_name, new_len);
476 				hpfs_mark_4buffers_dirty(&qbh1);
477 				hpfs_brelse4(&qbh1);
478 				goto end;
479 			}
480 			hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
481 			err = -EFSERROR;
482 			goto end1;
483 		}
484 		err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
485 		goto end1;
486 	}
487 
488 	if (new_dir == old_dir) hpfs_brelse4(&qbh);
489 
490 	hpfs_lock_creation(i->i_sb);
491 	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de, 1))) {
492 		hpfs_unlock_creation(i->i_sb);
493 		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
494 		err = r == 1 ? -ENOSPC : -EFSERROR;
495 		if (new_dir != old_dir) hpfs_brelse4(&qbh);
496 		goto end1;
497 	}
498 
499 	if (new_dir == old_dir)
500 		if (!(dep = map_dirent(old_dir, old_dir->i_hpfs_dno, (char *)old_name, old_len, &dno, &qbh))) {
501 			hpfs_unlock_creation(i->i_sb);
502 			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
503 			err = -ENOENT;
504 			goto end1;
505 		}
506 
507 	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
508 		hpfs_unlock_creation(i->i_sb);
509 		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
510 		err = r == 2 ? -ENOSPC : -EFSERROR;
511 		goto end1;
512 	}
513 	hpfs_unlock_creation(i->i_sb);
514 
515 	end:
516 	i->i_hpfs_parent_dir = new_dir->i_ino;
517 	if (S_ISDIR(i->i_mode)) {
518 		new_dir->i_nlink++;
519 		old_dir->i_nlink--;
520 	}
521 	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
522 		fnode->up = new_dir->i_ino;
523 		fnode->len = new_len;
524 		memcpy(fnode->name, new_name, new_len>15?15:new_len);
525 		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
526 		mark_buffer_dirty(bh);
527 		brelse(bh);
528 	}
529 	i->i_hpfs_conv = i->i_sb->s_hpfs_conv;
530 	hpfs_decide_conv(i, (char *)new_name, new_len);
531 	end1:
532 	hpfs_unlock_3inodes(old_dir, new_dir, i);
533 	return err;
534 }
535