1/*
2 *  linux/fs/umsdos/namei.c
3 *
4 *      Written 1993 by Jacques Gelinas
5 *      Inspired from linux/fs/msdos/... by Werner Almesberger
6 *
7 * Maintain and access the --linux alternate directory file.
8 */
9 /*
10  * You are in the maze of twisted functions - half of them shouldn't
11  * be here...
12  */
13
14#include <linux/errno.h>
15#include <linux/kernel.h>
16#include <linux/sched.h>
17#include <linux/types.h>
18#include <linux/fcntl.h>
19#include <linux/stat.h>
20#include <linux/string.h>
21#include <linux/msdos_fs.h>
22#include <linux/umsdos_fs.h>
23#include <linux/slab.h>
24
25#define UMSDOS_DIR_LOCK
26
27#ifdef UMSDOS_DIR_LOCK
28
29static inline void u_sleep_on (struct inode *dir)
30{
31	sleep_on (&dir->u.umsdos_i.dir_info.p);
32}
33
34static inline void u_wake_up (struct inode *dir)
35{
36    	wake_up (&dir->u.umsdos_i.dir_info.p);
37}
38
39/*
40 * Wait for creation exclusivity.
41 * Return 0 if the dir was already available.
42 * Return 1 if a wait was necessary.
43 * When 1 is return, it means a wait was done. It does not
44 * mean the directory is available.
45 */
46static int umsdos_waitcreate (struct inode *dir)
47{
48	int ret = 0;
49
50	if (dir->u.umsdos_i.dir_info.creating
51	    && dir->u.umsdos_i.dir_info.pid != current->pid) {
52	    	PRINTK (("creating && dir_info.pid=%lu, current->pid=%u\n", dir->u.umsdos_i.dir_info.pid, current->pid));
53	    	u_sleep_on (dir);
54		ret = 1;
55	}
56	return ret;
57}
58
59/*
60 * Wait for any lookup process to finish
61 */
62static void umsdos_waitlookup (struct inode *dir)
63{
64	while (dir->u.umsdos_i.dir_info.looking) {
65	    	u_sleep_on (dir);
66	}
67}
68
69/*
70 * Lock all other process out of this directory.
71 */
72/* #Specification: file creation / not atomic
73 * File creation is a two step process. First we create (allocate)
74 * an entry in the EMD file and then (using the entry offset) we
75 * build a unique name for MSDOS. We create this name in the msdos
76 * space.
77 *
78 * We have to use semaphore (sleep_on/wake_up) to prevent lookup
79 * into a directory when we create a file or directory and to
80 * prevent creation while a lookup is going on. Since many lookup
81 * may happen at the same time, the semaphore is a counter.
82 *
83 * Only one creation is allowed at the same time. This protection
84 * may not be necessary. The problem arise mainly when a lookup
85 * or a readdir is done while a file is partially created. The
86 * lookup process see that as a "normal" problem and silently
87 * erase the file from the EMD file. Normal because a file
88 * may be erased during a MSDOS session, but not removed from
89 * the EMD file.
90 *
91 * The locking is done on a directory per directory basis. Each
92 * directory inode has its wait_queue.
93 *
94 * For some operation like hard link, things even get worse. Many
95 * creation must occur at once (atomic). To simplify the design
96 * a process is allowed to recursively lock the directory for
97 * creation. The pid of the locking process is kept along with
98 * a counter so a second level of locking is granted or not.
99 */
100void umsdos_lockcreate (struct inode *dir)
101{
102	/*
103	 * Wait for any creation process to finish except
104	 * if we (the process) own the lock
105	 */
106	while (umsdos_waitcreate (dir) != 0);
107	dir->u.umsdos_i.dir_info.creating++;
108	dir->u.umsdos_i.dir_info.pid = current->pid;
109	umsdos_waitlookup (dir);
110}
111
112/*
113 * Lock all other process out of those two directories.
114 */
115static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
116{
117	/*
118	 * We must check that both directory are available before
119	 * locking anyone of them. This is to avoid some deadlock.
120	 * Thanks to dglaude@is1.vub.ac.be (GLAUDE DAVID) for pointing
121	 * this to me.
122	 */
123	while (1) {
124		if (umsdos_waitcreate (dir1) == 0
125		    && umsdos_waitcreate (dir2) == 0) {
126			/* We own both now */
127			dir1->u.umsdos_i.dir_info.creating++;
128			dir1->u.umsdos_i.dir_info.pid = current->pid;
129			dir2->u.umsdos_i.dir_info.creating++;
130			dir2->u.umsdos_i.dir_info.pid = current->pid;
131			break;
132		}
133	}
134	umsdos_waitlookup (dir1);
135	umsdos_waitlookup (dir2);
136}
137
138/*
139 * Wait until creation is finish in this directory.
140 */
141void umsdos_startlookup (struct inode *dir)
142{
143	while (umsdos_waitcreate (dir) != 0);
144	dir->u.umsdos_i.dir_info.looking++;
145}
146
147/*
148 * Unlock the directory.
149 */
150void umsdos_unlockcreate (struct inode *dir)
151{
152	dir->u.umsdos_i.dir_info.creating--;
153	if (dir->u.umsdos_i.dir_info.creating < 0) {
154		printk ("UMSDOS: dir->u.umsdos_i.dir_info.creating < 0: %d"
155			,dir->u.umsdos_i.dir_info.creating);
156	}
157    	u_wake_up (dir);
158}
159
160/*
161 * Tell directory lookup is over.
162 */
163void umsdos_endlookup (struct inode *dir)
164{
165	dir->u.umsdos_i.dir_info.looking--;
166	if (dir->u.umsdos_i.dir_info.looking < 0) {
167		printk ("UMSDOS: dir->u.umsdos_i.dir_info.looking < 0: %d"
168			,dir->u.umsdos_i.dir_info.looking);
169	}
170    	u_wake_up (dir);
171}
172
173#else
174static void umsdos_lockcreate (struct inode *dir)
175{
176}
177static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
178{
179}
180void umsdos_startlookup (struct inode *dir)
181{
182}
183static void umsdos_unlockcreate (struct inode *dir)
184{
185}
186void umsdos_endlookup (struct inode *dir)
187{
188}
189
190#endif
191
192static int umsdos_nevercreat (struct inode *dir, struct dentry *dentry,
193				int errcod)
194{
195	int ret = 0;
196
197	if (umsdos_is_pseudodos (dir, dentry)) {
198		/* #Specification: pseudo root / any file creation /DOS
199		 * The pseudo sub-directory /DOS can't be created!
200		 * EEXIST is returned.
201		 *
202		 * The pseudo sub-directory /DOS can't be removed!
203		 * EPERM is returned.
204		 */
205		ret = errcod;
206	}
207	return ret;
208}
209
210/*
211 * Add a new file (ordinary or special) into the alternate directory.
212 * The file is added to the real MSDOS directory. If successful, it
213 * is then added to the EMD file.
214 *
215 * Return the status of the operation. 0 mean success.
216 *
217 * #Specification: create / file exists in DOS
218 * Here is a situation: we are trying to create a file with
219 * UMSDOS. The file is unknown to UMSDOS but already
220 * exists in the DOS directory.
221 *
222 * Here is what we are NOT doing:
223 *
224 * We could silently assume that everything is fine
225 * and allows the creation to succeed.
226 *
227 * It is possible not all files in the partition
228 * are meant to be visible from linux. By trying to create
229 * those file in some directory, one user may get access
230 * to those file without proper permissions. Looks like
231 * a security hole to me. Off course sharing a file system
232 * with DOS is some kind of security hole :-)
233 *
234 * So ?
235 *
236 * We return EEXIST in this case.
237 * The same is true for directory creation.
238 */
239static int umsdos_create_any (struct inode *dir, struct dentry *dentry,
240				int mode, int rdev, char flags)
241{
242	struct dentry *fake;
243	struct inode *inode;
244	int ret;
245	struct umsdos_info info;
246
247	ret = umsdos_nevercreat (dir, dentry, -EEXIST);
248	if (ret)
249		goto out;
250
251	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
252	if (ret)
253		goto out;
254
255	info.entry.mode = mode;
256	info.entry.rdev = rdev;
257	info.entry.flags = flags;
258	info.entry.uid = current->fsuid;
259	info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
260	info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME;
261	info.entry.nlink = 1;
262	ret = umsdos_newentry (dentry->d_parent, &info);
263	if (ret)
264		goto out;
265
266	/* do a real lookup to get the short name dentry */
267	fake = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
268	ret = PTR_ERR(fake);
269	if (IS_ERR(fake))
270		goto out_remove;
271
272	/* should not exist yet ... */
273	ret = -EEXIST;
274	if (fake->d_inode)
275		goto out_remove_dput;
276
277	ret = msdos_create (dir, fake, S_IFREG | 0777);
278	if (ret)
279		goto out_remove_dput;
280
281	inode = fake->d_inode;
282	atomic_inc(&inode->i_count);
283	d_instantiate (dentry, inode);
284	dput(fake);
285	if (atomic_read(&inode->i_count) > 1) {
286		printk(KERN_WARNING
287			"umsdos_create_any: %s/%s, ino=%ld, icount=%d??\n",
288			dentry->d_parent->d_name.name, dentry->d_name.name,
289			inode->i_ino, atomic_read(&inode->i_count));
290	}
291	umsdos_lookup_patch_new(dentry, &info);
292
293out:
294	return ret;
295
296	/* Creation failed ... remove the EMD entry */
297out_remove_dput:
298	dput(fake);
299out_remove:
300	if (ret == -EEXIST)
301		printk(KERN_WARNING "UMSDOS: out of sync, deleting %s/%s\n",
302			dentry->d_parent->d_name.name, info.fake.fname);
303	umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));
304	goto out;
305}
306
307/*
308 * Add a new file into the alternate directory.
309 * The file is added to the real MSDOS directory. If successful, it
310 * is then added to the EMD file.
311 *
312 * Return the status of the operation. 0 mean success.
313 */
314int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode)
315{
316	return umsdos_create_any (dir, dentry, mode, 0, 0);
317}
318
319
320/*
321 * Initialise the new_entry from the old for a rename operation.
322 * (Only useful for umsdos_rename_f() below).
323 */
324static void umsdos_ren_init (struct umsdos_info *new_info,
325			     struct umsdos_info *old_info)
326{
327	new_info->entry.mode = old_info->entry.mode;
328	new_info->entry.rdev = old_info->entry.rdev;
329	new_info->entry.uid = old_info->entry.uid;
330	new_info->entry.gid = old_info->entry.gid;
331	new_info->entry.ctime = old_info->entry.ctime;
332	new_info->entry.atime = old_info->entry.atime;
333	new_info->entry.mtime = old_info->entry.mtime;
334	new_info->entry.flags = old_info->entry.flags;
335	new_info->entry.nlink = old_info->entry.nlink;
336}
337
338/*
339 * Rename a file (move) in the file system.
340 */
341
342static int umsdos_rename_f (struct inode *old_dir, struct dentry *old_dentry,
343			    struct inode *new_dir, struct dentry *new_dentry,
344			    int flags)
345{
346	struct inode *old_inode = old_dentry->d_inode;
347	struct dentry *old, *new, *old_emd;
348	int err, ret;
349	struct umsdos_info old_info;
350	struct umsdos_info new_info;
351
352 	ret = -EPERM;
353	err = umsdos_parse (old_dentry->d_name.name,
354				old_dentry->d_name.len, &old_info);
355	if (err)
356		goto out;
357	err = umsdos_parse (new_dentry->d_name.name,
358				new_dentry->d_name.len, &new_info);
359	if (err)
360		goto out;
361
362	/* Get the EMD dentry for the old parent */
363	old_emd = umsdos_get_emd_dentry(old_dentry->d_parent);
364	ret = PTR_ERR(old_emd);
365	if (IS_ERR(old_emd))
366		goto out;
367
368	umsdos_lockcreate2 (old_dir, new_dir);
369
370	ret = umsdos_findentry(old_emd->d_parent, &old_info, 0);
371	if (ret)
372		goto out_unlock;
373
374	err = umsdos_findentry(new_dentry->d_parent, &new_info, 0);
375	if (err == 0) {
376		/* check whether it _really_ exists ... */
377		ret = -EEXIST;
378		if (new_dentry->d_inode)
379			goto out_unlock;
380
381		/* bogus lookup? complain and fix up the EMD ... */
382		printk(KERN_WARNING
383			"umsdos_rename_f: entry %s/%s exists, inode NULL??\n",
384			new_dentry->d_parent->d_name.name, new_info.entry.name);
385		err = umsdos_delentry(new_dentry->d_parent, &new_info,
386					S_ISDIR(new_info.entry.mode));
387	}
388
389	umsdos_ren_init (&new_info, &old_info);
390	if (flags)
391		new_info.entry.flags = flags;
392	ret = umsdos_newentry (new_dentry->d_parent, &new_info);
393	if (ret)
394		goto out_unlock;
395
396	/* If we're moving a hardlink, drop it first */
397	if (old_info.entry.flags & UMSDOS_HLINK) {
398		d_drop(old_dentry);
399	}
400
401	old = umsdos_covered(old_dentry->d_parent, old_info.fake.fname,
402					old_info.fake.len);
403	ret = PTR_ERR(old);
404	if (IS_ERR(old))
405		goto out_unlock;
406	/* make sure it's the same inode! */
407	ret = -ENOENT;
408	/*
409	 * note: for hardlinks they will be different!
410	 *  old_inode will contain inode of .LINKxxx file containing data, and
411	 *  old->d_inode will contain inode of file containing path to .LINKxxx file
412	 */
413	if (!(old_info.entry.flags & UMSDOS_HLINK)) {
414	 	if (old->d_inode != old_inode)
415 			goto out_dput;
416	}
417
418	new = umsdos_covered(new_dentry->d_parent, new_info.fake.fname,
419					new_info.fake.len);
420	ret = PTR_ERR(new);
421	if (IS_ERR(new))
422		goto out_dput;
423
424	/* Do the msdos-level rename */
425	ret = msdos_rename (old_dir, old, new_dir, new);
426
427	dput(new);
428
429	/* If the rename failed, remove the new EMD entry */
430	if (ret != 0) {
431		umsdos_delentry (new_dentry->d_parent, &new_info,
432				 S_ISDIR (new_info.entry.mode));
433		goto out_dput;
434	}
435
436	/*
437	 * Rename successful ... remove the old name from the EMD.
438	 * Note that we use the EMD parent here, as the old dentry
439	 * may have moved to a new parent ...
440	 */
441	err = umsdos_delentry (old_emd->d_parent, &old_info,
442				S_ISDIR (old_info.entry.mode));
443	if (err) {
444		/* Failed? Complain a bit, but don't fail the operation */
445		printk(KERN_WARNING
446			"umsdos_rename_f: delentry %s/%s failed, error=%d\n",
447			old_emd->d_parent->d_name.name, old_info.entry.name,
448			err);
449	}
450
451	/*
452	 * Update f_pos so notify_change will succeed
453	 * if the file was already in use.
454	 */
455	umsdos_set_dirinfo_new(old_dentry, new_info.f_pos);
456
457	/* dput() the dentry if we haven't already */
458out_dput:
459	dput(old);
460
461out_unlock:
462	dput(old_emd);
463	umsdos_unlockcreate (old_dir);
464	umsdos_unlockcreate (new_dir);
465
466out:
467	Printk ((" _ret=%d\n", ret));
468	return ret;
469}
470
471/*
472 * Setup a Symbolic link or a (pseudo) hard link
473 * Return a negative error code or 0 if OK.
474 */
475/* #Specification: symbolic links / strategy
476 * A symbolic link is simply a file which holds a path. It is
477 * implemented as a normal MSDOS file (not very space efficient :-()
478 *
479 * I see two different ways to do this: One is to place the link data
480 * in unused entries of the EMD file; the other is to have a separate
481 * file dedicated to hold all symbolic links data.
482 *
483 * Let's go for simplicity...
484 */
485
486/*
487 * AV. Should be called with dir->i_sem down.
488 */
489static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry,
490			const char *symname, int mode, char flags)
491{
492	int ret, len;
493
494	ret = umsdos_create_any (dir, dentry, mode, 0, flags);
495	if (ret) {
496		printk(KERN_WARNING
497			"umsdos_symlink: create failed, ret=%d\n", ret);
498		goto out;
499	}
500
501	len = strlen (symname) + 1;
502	ret = block_symlink(dentry->d_inode, symname, len);
503	if (ret < 0)
504		goto out_unlink;
505out:
506	return ret;
507
508out_unlink:
509	printk(KERN_WARNING "umsdos_symlink: write failed, unlinking\n");
510	UMSDOS_unlink (dir, dentry);
511	d_drop(dentry);
512	goto out;
513}
514
515/*
516 * Setup a Symbolic link.
517 * Return a negative error code or 0 if OK.
518 */
519int UMSDOS_symlink ( struct inode *dir, struct dentry *dentry,
520		 const char *symname)
521{
522	return umsdos_symlink_x (dir, dentry, symname, S_IFLNK | 0777, 0);
523}
524
525/*
526 * Add a link to an inode in a directory
527 */
528int UMSDOS_link (struct dentry *olddentry, struct inode *dir,
529		 struct dentry *dentry)
530{
531	struct inode *oldinode = olddentry->d_inode;
532	struct inode *olddir = olddentry->d_parent->d_inode;
533	struct dentry *temp;
534	char *path;
535	unsigned long buffer;
536	int ret;
537	struct umsdos_info old_info;
538	struct umsdos_info hid_info;
539
540#ifdef UMSDOS_DEBUG_VERBOSE
541printk("umsdos_link: new %s/%s -> %s/%s\n",
542dentry->d_parent->d_name.name, dentry->d_name.name,
543olddentry->d_parent->d_name.name, olddentry->d_name.name);
544#endif
545
546	ret = -EPERM;
547	if (S_ISDIR (oldinode->i_mode))
548		goto out;
549
550	ret = umsdos_nevercreat (dir, dentry, -EPERM);
551	if (ret)
552		goto out;
553
554	ret = -ENOMEM;
555	buffer = get_free_page(GFP_KERNEL);
556	if (!buffer)
557		goto out;
558
559	/*
560	 * Lock the link parent if it's not the same directory.
561	 */
562	ret = -EDEADLOCK;
563	if (olddir != dir) {
564		if (atomic_read(&olddir->i_sem.count) < 1)
565			goto out_free;
566		down(&olddir->i_sem);
567	}
568
569	/*
570	 * Parse the name and get the visible directory entry.
571	 */
572	ret = umsdos_parse (olddentry->d_name.name, olddentry->d_name.len,
573				&old_info);
574	if (ret)
575		goto out_unlock;
576	ret = umsdos_findentry (olddentry->d_parent, &old_info, 1);
577	if (ret) {
578printk("UMSDOS_link: %s/%s not in EMD, ret=%d\n",
579olddentry->d_parent->d_name.name, olddentry->d_name.name, ret);
580		goto out_unlock;
581	}
582
583	/*
584	 * If the visible dentry is a pseudo-hardlink, the original
585	 * file must be already hidden.
586	 */
587	if (!(old_info.entry.flags & UMSDOS_HLINK)) {
588		int err;
589
590		/* create a hidden link name */
591		ret = umsdos_newhidden (olddentry->d_parent, &hid_info);
592		if (ret) {
593printk("umsdos_link: can't make hidden %s/%s, ret=%d\n",
594olddentry->d_parent->d_name.name, hid_info.entry.name, ret);
595			goto out_unlock;
596		}
597
598		/*
599		 * Make a dentry and rename the original file ...
600		 */
601		temp = umsdos_lookup_dentry(olddentry->d_parent,
602						hid_info.entry.name,
603						hid_info.entry.name_len, 0);
604		ret = PTR_ERR(temp);
605		if (IS_ERR(temp)) {
606printk("umsdos_link: lookup %s/%s failed, ret=%d\n",
607dentry->d_parent->d_name.name, hid_info.entry.name, ret);
608			goto cleanup;
609		}
610		/* rename the link to the hidden location ... */
611		ret = umsdos_rename_f(olddir, olddentry, olddir, temp,
612					UMSDOS_HIDDEN);
613		d_move(olddentry, temp);
614		dput(temp);
615		if (ret) {
616printk("umsdos_link: rename to %s/%s failed, ret=%d\n",
617temp->d_parent->d_name.name, temp->d_name.name, ret);
618			goto cleanup;
619		}
620		/* mark the inode as a hardlink */
621		oldinode->u.umsdos_i.i_is_hlink = 1;
622
623		/*
624		 * Capture the path to the hidden link.
625		 */
626		path = umsdos_d_path(olddentry, (char *) buffer, PAGE_SIZE);
627Printk(("umsdos_link: hidden link path=%s\n", path));
628
629		/*
630		 * Recreate a dentry for the original name and symlink it,
631		 * then symlink the new dentry. Don't give up if one fails,
632		 * or we'll lose the file completely!
633		 *
634		 * Note: this counts as the "original" reference, so we
635		 * don't increment i_nlink for this one.
636		 */
637		temp = umsdos_lookup_dentry(olddentry->d_parent,
638						old_info.entry.name,
639						old_info.entry.name_len, 0);
640		ret = PTR_ERR(temp);
641		if (!IS_ERR(temp)) {
642			ret = umsdos_symlink_x (olddir, temp, path,
643						S_IFREG | 0777, UMSDOS_HLINK);
644			dput(temp);
645		}
646
647		/* This symlink increments i_nlink (see below.) */
648		err = umsdos_symlink_x (dir, dentry, path,
649					S_IFREG | 0777, UMSDOS_HLINK);
650		/* fold the two errors */
651		if (!ret)
652			ret = err;
653		goto out_unlock;
654
655		/* creation failed ... remove the link entry */
656	cleanup:
657printk("umsdos_link: link failed, ret=%d, removing %s/%s\n",
658ret, olddentry->d_parent->d_name.name, hid_info.entry.name);
659		err = umsdos_delentry(olddentry->d_parent, &hid_info, 0);
660		goto out_unlock;
661	}
662
663Printk(("UMSDOS_link: %s/%s already hidden\n",
664olddentry->d_parent->d_name.name, olddentry->d_name.name));
665	/*
666	 * The original file is already hidden, and we need to get
667	 * the dentry for its real name, not the visible name.
668	 * N.B. make sure it's the hidden inode ...
669	 */
670	if (!oldinode->u.umsdos_i.i_is_hlink)
671		printk("UMSDOS_link: %s/%s hidden, ino=%ld not hlink??\n",
672			olddentry->d_parent->d_name.name,
673			olddentry->d_name.name, oldinode->i_ino);
674
675	/*
676	 * In order to get the correct (real) inode, we just drop
677	 * the original dentry.
678	 */
679	d_drop(olddentry);
680Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n",
681olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname));
682
683	/* Do a real lookup to get the short name dentry */
684	temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname,
685					old_info.fake.len);
686	ret = PTR_ERR(temp);
687	if (IS_ERR(temp))
688		goto out_unlock;
689
690	/* now resolve the link ... */
691	temp = umsdos_solve_hlink(temp);
692	ret = PTR_ERR(temp);
693	if (IS_ERR(temp))
694		goto out_unlock;
695	path = umsdos_d_path(temp, (char *) buffer, PAGE_SIZE);
696	dput(temp);
697Printk(("umsdos_link: %s/%s already hidden, path=%s\n",
698olddentry->d_parent->d_name.name, olddentry->d_name.name, path));
699
700	/* finally we can symlink it ... */
701	ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777,UMSDOS_HLINK);
702
703out_unlock:
704	/* remain locked for the call to notify_change ... */
705	if (ret == 0) {
706		struct iattr newattrs;
707
708		/* Do a real lookup to get the short name dentry */
709		temp = umsdos_covered(olddentry->d_parent,
710					old_info.fake.fname,
711					old_info.fake.len);
712		ret = PTR_ERR(temp);
713		if (IS_ERR(temp))
714			goto out_unlock2;
715
716		/* now resolve the link ... */
717		temp = umsdos_solve_hlink(temp);
718		ret = PTR_ERR(temp);
719		if (IS_ERR(temp))
720			goto out_unlock2;
721
722
723#ifdef UMSDOS_PARANOIA
724if (!oldinode->u.umsdos_i.i_is_hlink)
725printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",
726olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);
727#endif
728		temp->d_inode->i_nlink++;
729Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",
730olddentry->d_parent->d_name.name, olddentry->d_name.name,
731oldinode->i_ino, oldinode->i_nlink));
732		newattrs.ia_valid = 0;
733		ret = umsdos_notify_change_locked(temp, &newattrs);
734 		if (ret == 0)
735			mark_inode_dirty(temp->d_inode);
736		dput(temp);
737out_unlock2:
738		if (ret == 0)
739			mark_inode_dirty(olddentry->d_inode);
740	}
741	if (olddir != dir)
742		up(&olddir->i_sem);
743
744out_free:
745	free_page(buffer);
746out:
747	Printk (("umsdos_link %d\n", ret));
748	return ret;
749}
750
751
752/*
753 * Add a sub-directory in a directory
754 */
755/* #Specification: mkdir / Directory already exist in DOS
756 * We do the same thing as for file creation.
757 * For all user it is an error.
758 */
759/* #Specification: mkdir / umsdos directory / create EMD
760 * When we created a new sub-directory in a UMSDOS
761 * directory (one with full UMSDOS semantics), we
762 * create immediately an EMD file in the new
763 * sub-directory so it inherits UMSDOS semantics.
764 */
765int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode)
766{
767	struct dentry *temp;
768	struct inode *inode;
769	int ret, err;
770	struct umsdos_info info;
771
772	ret = umsdos_nevercreat (dir, dentry, -EEXIST);
773	if (ret)
774		goto out;
775
776	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
777	if (ret)
778		goto out;
779
780	info.entry.mode = mode | S_IFDIR;
781	info.entry.rdev = 0;
782	info.entry.uid = current->fsuid;
783	info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
784	info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME;
785	info.entry.flags = 0;
786	info.entry.nlink = 1;
787	ret = umsdos_newentry (dentry->d_parent, &info);
788	if (ret)
789		goto out;
790
791	/* lookup the short name dentry */
792	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
793	ret = PTR_ERR(temp);
794	if (IS_ERR(temp))
795		goto out_remove;
796
797	/* Make sure the short name doesn't exist */
798	ret = -EEXIST;
799	if (temp->d_inode) {
800printk("umsdos_mkdir: short name %s/%s exists\n",
801dentry->d_parent->d_name.name, info.fake.fname);
802		goto out_remove_dput;
803	}
804
805	ret = msdos_mkdir (dir, temp, mode);
806	if (ret)
807		goto out_remove_dput;
808
809	/*
810	 * Lock the inode to protect the EMD creation ...
811	 */
812	inode = temp->d_inode;
813	down(&inode->i_sem);
814
815	atomic_inc(&inode->i_count);
816	d_instantiate(dentry, inode);
817
818	/* N.B. this should have an option to create the EMD ... */
819	umsdos_lookup_patch_new(dentry, &info);
820
821	/*
822	 * Create the EMD file, and set up the dir so it is
823	 * promoted to EMD with the EMD file invisible.
824	 *
825	 * N.B. error return if EMD fails?
826	 */
827	err = umsdos_make_emd(dentry);
828	umsdos_setup_dir(dentry);
829
830	up(&inode->i_sem);
831	dput(temp);
832
833out:
834	Printk(("umsdos_mkdir: %s/%s, ret=%d\n",
835		dentry->d_parent->d_name.name, dentry->d_name.name, ret));
836	return ret;
837
838	/* an error occurred ... remove EMD entry. */
839out_remove_dput:
840	dput(temp);
841out_remove:
842	umsdos_delentry (dentry->d_parent, &info, 1);
843	goto out;
844}
845
846/*
847 * Add a new device special file into a directory.
848 *
849 * #Specification: Special files / strategy
850 * Device special file, pipes, etc ... are created like normal
851 * file in the msdos file system. Of course they remain empty.
852 *
853 * One strategy was to create those files only in the EMD file
854 * since they were not important for MSDOS. The problem with
855 * that, is that there were not getting inode number allocated.
856 * The MSDOS filesystems is playing a nice game to fake inode
857 * number, so why not use it.
858 *
859 * The absence of inode number compatible with those allocated
860 * for ordinary files was causing major trouble with hard link
861 * in particular and other parts of the kernel I guess.
862 */
863int UMSDOS_mknod (struct inode *dir, struct dentry *dentry,
864		 int mode, int rdev)
865{
866	return umsdos_create_any (dir, dentry, mode, rdev, 0);
867}
868
869/*
870 * Remove a sub-directory.
871 */
872int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry)
873{
874	struct dentry *temp;
875	int ret, err, empty;
876	struct umsdos_info info;
877
878	ret = umsdos_nevercreat (dir, dentry, -EPERM);
879	if (ret)
880		goto out;
881
882	ret = -EBUSY;
883	if (!d_unhashed(dentry))
884		goto out;
885
886	/* check whether the EMD is empty */
887	ret = -ENOTEMPTY;
888	empty = umsdos_isempty (dentry);
889
890	/* Have to remove the EMD file? */
891	if (empty == 1) {
892		struct dentry *demd;
893
894		demd = umsdos_get_emd_dentry(dentry);
895		if (!IS_ERR(demd)) {
896			err = -ENOENT;
897			if (demd->d_inode)
898				err = msdos_unlink (dentry->d_inode, demd);
899Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err));
900#ifdef UMSDOS_PARANOIA
901if (err)
902printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n",
903demd->d_parent->d_name.name, demd->d_name.name, err);
904#endif
905			if (!err) {
906				d_delete(demd);
907				ret = 0;
908			}
909			dput(demd);
910		}
911	} else if (empty == 2)
912		ret = 0;
913	if (ret)
914		goto out;
915
916	umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
917	/* Call findentry to complete the mangling */
918	umsdos_findentry (dentry->d_parent, &info, 2);
919	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
920	ret = PTR_ERR(temp);
921	if (IS_ERR(temp))
922		goto out;
923	/*
924	 * Attempt to remove the msdos name.
925	 */
926	ret = msdos_rmdir (dir, temp);
927	if (ret && ret != -ENOENT)
928		goto out_dput;
929
930	d_delete(temp);
931	/* OK so far ... remove the name from the EMD */
932	ret = umsdos_delentry (dentry->d_parent, &info, 1);
933#ifdef UMSDOS_PARANOIA
934if (ret)
935printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret);
936#endif
937
938	/* dput() temp if we didn't do it above */
939out_dput:
940	dput(temp);
941
942out:
943	Printk (("umsdos_rmdir %d\n", ret));
944	return ret;
945}
946
947
948/*
949 * Remove a file from the directory.
950 *
951 * #Specification: hard link / deleting a link
952 * When we delete a file and this file is a link,
953 * we must subtract 1 from the nlink field of the
954 * hidden link.
955 *
956 * If the count goes to 0, we delete this hidden
957 * link too.
958 */
959int UMSDOS_unlink (struct inode *dir, struct dentry *dentry)
960{
961	struct dentry *temp, *link = NULL;
962	struct inode *inode;
963	int ret;
964	struct umsdos_info info;
965
966Printk(("UMSDOS_unlink: entering %s/%s\n",
967dentry->d_parent->d_name.name, dentry->d_name.name));
968
969	ret = umsdos_nevercreat (dir, dentry, -EPERM);
970	if (ret)
971		goto out;
972
973	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
974	if (ret)
975		goto out;
976
977	umsdos_lockcreate (dir);
978	ret = umsdos_findentry (dentry->d_parent, &info, 1);
979	if (ret) {
980printk("UMSDOS_unlink: %s/%s not in EMD, ret=%d\n",
981dentry->d_parent->d_name.name, dentry->d_name.name, ret);
982		goto out_unlock;
983	}
984
985Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname));
986
987	/*
988	 * Note! If this is a hardlink and the names are aliased,
989	 * the short-name lookup will return the hardlink dentry.
990	 * In order to get the correct (real) inode, we just drop
991	 * the original dentry.
992	 */
993	if (info.entry.flags & UMSDOS_HLINK) {
994		d_drop(dentry);
995	}
996
997	/* Do a real lookup to get the short name dentry */
998	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
999	ret = PTR_ERR(temp);
1000	if (IS_ERR(temp))
1001		goto out_unlock;
1002
1003	/*
1004	 * Resolve hardlinks now, but defer processing until later.
1005	 */
1006	if (info.entry.flags & UMSDOS_HLINK) {
1007		link = umsdos_solve_hlink(dget(temp));
1008	}
1009
1010	/* Delete the EMD entry */
1011	ret = umsdos_delentry (dentry->d_parent, &info, 0);
1012	if (ret && ret != -ENOENT) {
1013		printk(KERN_WARNING "UMSDOS_unlink: delentry %s, error=%d\n",
1014			info.entry.name, ret);
1015		goto out_dput;
1016	}
1017
1018	ret = msdos_unlink(dir, temp);
1019	if (!ret)
1020		d_delete(temp);
1021#ifdef UMSDOS_PARANOIA
1022if (ret)
1023printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n",
1024temp->d_parent->d_name.name, temp->d_name.name, ret);
1025#endif
1026
1027	/* dput() temp if we didn't do it above */
1028out_dput:
1029	dput(temp);
1030
1031out_unlock:
1032	umsdos_unlockcreate (dir);
1033
1034	/*
1035	 * Now check for deferred handling of a hardlink.
1036	 */
1037	if (!link)
1038		goto out;
1039
1040	if (IS_ERR(link)) {
1041printk("umsdos_unlink: failed to resolve %s/%s\n",
1042dentry->d_parent->d_name.name, dentry->d_name.name);
1043		if (!ret)
1044			ret = PTR_ERR(link);
1045		goto out;
1046	}
1047
1048Printk(("umsdos_unlink: link %s/%s deferred, pending ret=%d\n",
1049link->d_parent->d_name.name, link->d_name.name, ret));
1050
1051	/* already have an error? */
1052	if (ret)
1053		goto out_cleanup;
1054
1055	/* make sure the link exists ... */
1056	inode = link->d_inode;
1057	if (!inode) {
1058		printk(KERN_WARNING "umsdos_unlink: hard link not found\n");
1059		goto out_cleanup;
1060	}
1061
1062	/*
1063	 * If this was the last linked reference, delete it now.
1064	 *
1065	 * N.B. Deadlock problem? We should be holding the lock
1066	 * for the hardlink's parent, but another process might
1067	 * be holding that lock waiting for us to finish ...
1068	 */
1069	if (inode->i_nlink <= 1) {
1070		ret = UMSDOS_unlink (link->d_parent->d_inode, link);
1071		if (ret) {
1072			printk(KERN_WARNING
1073				"umsdos_unlink: link removal failed, ret=%d\n",
1074				 ret);
1075		} else
1076			d_delete(link);
1077	} else {
1078		struct iattr newattrs;
1079		inode->i_nlink--;
1080		newattrs.ia_valid = 0;
1081		ret = umsdos_notify_change_locked(link, &newattrs);
1082		if (!ret)
1083			mark_inode_dirty(link->d_inode);
1084	}
1085
1086out_cleanup:
1087	d_drop(link);
1088	dput(link);
1089
1090out:
1091	Printk (("umsdos_unlink %d\n", ret));
1092	return ret;
1093}
1094
1095/*
1096 * Rename (move) a file.
1097 */
1098int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry,
1099		   struct inode *new_dir, struct dentry *new_dentry)
1100{
1101	int ret;
1102
1103	ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST);
1104	if (ret)
1105		return ret;
1106
1107		/*
1108		 * If the target already exists, delete it first.
1109		 */
1110	if (new_dentry->d_inode) {
1111		dget(new_dentry);
1112		if (S_ISDIR(old_dentry->d_inode->i_mode))
1113			ret = UMSDOS_rmdir (new_dir, new_dentry);
1114		else
1115			ret = UMSDOS_unlink (new_dir, new_dentry);
1116		if (!ret)
1117			d_drop(new_dentry);
1118		dput(new_dentry);
1119		if (ret)
1120			return ret;
1121	}
1122	ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0);
1123	return ret;
1124}
1125