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 
u_sleep_on(struct inode * dir)29 static inline void u_sleep_on (struct inode *dir)
30 {
31 	sleep_on (&dir->u.umsdos_i.dir_info.p);
32 }
33 
u_wake_up(struct inode * dir)34 static 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  */
umsdos_waitcreate(struct inode * dir)46 static 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  */
umsdos_waitlookup(struct inode * dir)62 static 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  */
umsdos_lockcreate(struct inode * dir)100 void 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  */
umsdos_lockcreate2(struct inode * dir1,struct inode * dir2)115 static 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  */
umsdos_startlookup(struct inode * dir)141 void 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  */
umsdos_unlockcreate(struct inode * dir)150 void 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  */
umsdos_endlookup(struct inode * dir)163 void 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
umsdos_lockcreate(struct inode * dir)174 static void umsdos_lockcreate (struct inode *dir)
175 {
176 }
umsdos_lockcreate2(struct inode * dir1,struct inode * dir2)177 static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
178 {
179 }
umsdos_startlookup(struct inode * dir)180 void umsdos_startlookup (struct inode *dir)
181 {
182 }
umsdos_unlockcreate(struct inode * dir)183 static void umsdos_unlockcreate (struct inode *dir)
184 {
185 }
umsdos_endlookup(struct inode * dir)186 void umsdos_endlookup (struct inode *dir)
187 {
188 }
189 
190 #endif
191 
umsdos_nevercreat(struct inode * dir,struct dentry * dentry,int errcod)192 static 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  */
umsdos_create_any(struct inode * dir,struct dentry * dentry,int mode,int rdev,char flags)239 static 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 
293 out:
294 	return ret;
295 
296 	/* Creation failed ... remove the EMD entry */
297 out_remove_dput:
298 	dput(fake);
299 out_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  */
UMSDOS_create(struct inode * dir,struct dentry * dentry,int mode)314 int 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  */
umsdos_ren_init(struct umsdos_info * new_info,struct umsdos_info * old_info)324 static 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 
umsdos_rename_f(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,int flags)342 static 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 */
458 out_dput:
459 	dput(old);
460 
461 out_unlock:
462 	dput(old_emd);
463 	umsdos_unlockcreate (old_dir);
464 	umsdos_unlockcreate (new_dir);
465 
466 out:
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  */
umsdos_symlink_x(struct inode * dir,struct dentry * dentry,const char * symname,int mode,char flags)489 static 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;
505 out:
506 	return ret;
507 
508 out_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  */
UMSDOS_symlink(struct inode * dir,struct dentry * dentry,const char * symname)519 int 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  */
UMSDOS_link(struct dentry * olddentry,struct inode * dir,struct dentry * dentry)528 int 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
541 printk("umsdos_link: new %s/%s -> %s/%s\n",
542 dentry->d_parent->d_name.name, dentry->d_name.name,
543 olddentry->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) {
578 printk("UMSDOS_link: %s/%s not in EMD, ret=%d\n",
579 olddentry->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) {
593 printk("umsdos_link: can't make hidden %s/%s, ret=%d\n",
594 olddentry->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)) {
606 printk("umsdos_link: lookup %s/%s failed, ret=%d\n",
607 dentry->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) {
616 printk("umsdos_link: rename to %s/%s failed, ret=%d\n",
617 temp->d_parent->d_name.name, temp->d_name.name, ret);
618 			goto cleanup;
619 		}
620 		/*
621 		 * Capture the path to the hidden link.
622 		 */
623 		path = umsdos_d_path(olddentry, (char *) buffer, PAGE_SIZE);
624 		if (IS_ERR(path)) {
625 			ret = PTR_ERR(path);
626 			goto cleanup;
627 		}
628 Printk(("umsdos_link: hidden link path=%s\n", path));
629 
630 		/* mark the inode as a hardlink */
631 		oldinode->u.umsdos_i.i_is_hlink = 1;
632 
633 		/*
634 		 * Recreate a dentry for the original name and symlink it,
635 		 * then symlink the new dentry. Don't give up if one fails,
636 		 * or we'll lose the file completely!
637 		 *
638 		 * Note: this counts as the "original" reference, so we
639 		 * don't increment i_nlink for this one.
640 		 */
641 		temp = umsdos_lookup_dentry(olddentry->d_parent,
642 						old_info.entry.name,
643 						old_info.entry.name_len, 0);
644 		ret = PTR_ERR(temp);
645 		if (!IS_ERR(temp)) {
646 			ret = umsdos_symlink_x (olddir, temp, path,
647 						S_IFREG | 0777, UMSDOS_HLINK);
648 			dput(temp);
649 		}
650 
651 		/* This symlink increments i_nlink (see below.) */
652 		err = umsdos_symlink_x (dir, dentry, path,
653 					S_IFREG | 0777, UMSDOS_HLINK);
654 		/* fold the two errors */
655 		if (!ret)
656 			ret = err;
657 		goto out_unlock;
658 
659 		/* creation failed ... remove the link entry */
660 	cleanup:
661 printk("umsdos_link: link failed, ret=%d, removing %s/%s\n",
662 ret, olddentry->d_parent->d_name.name, hid_info.entry.name);
663 		err = umsdos_delentry(olddentry->d_parent, &hid_info, 0);
664 		goto out_unlock;
665 	}
666 
667 Printk(("UMSDOS_link: %s/%s already hidden\n",
668 olddentry->d_parent->d_name.name, olddentry->d_name.name));
669 	/*
670 	 * The original file is already hidden, and we need to get
671 	 * the dentry for its real name, not the visible name.
672 	 * N.B. make sure it's the hidden inode ...
673 	 */
674 	if (!oldinode->u.umsdos_i.i_is_hlink)
675 		printk("UMSDOS_link: %s/%s hidden, ino=%ld not hlink??\n",
676 			olddentry->d_parent->d_name.name,
677 			olddentry->d_name.name, oldinode->i_ino);
678 
679 	/*
680 	 * In order to get the correct (real) inode, we just drop
681 	 * the original dentry.
682 	 */
683 	d_drop(olddentry);
684 Printk(("UMSDOS_link: hard link %s/%s, fake=%s\n",
685 olddentry->d_parent->d_name.name, olddentry->d_name.name, old_info.fake.fname));
686 
687 	/* Do a real lookup to get the short name dentry */
688 	temp = umsdos_covered(olddentry->d_parent, old_info.fake.fname,
689 					old_info.fake.len);
690 	ret = PTR_ERR(temp);
691 	if (IS_ERR(temp))
692 		goto out_unlock;
693 
694 	/* now resolve the link ... */
695 	temp = umsdos_solve_hlink(temp);
696 	ret = PTR_ERR(temp);
697 	if (IS_ERR(temp))
698 		goto out_unlock;
699 	path = umsdos_d_path(temp, (char *) buffer, PAGE_SIZE);
700 	dput(temp);
701 	if (IS_ERR(path))
702 		goto out_unlock;
703 Printk(("umsdos_link: %s/%s already hidden, path=%s\n",
704 olddentry->d_parent->d_name.name, olddentry->d_name.name, path));
705 
706 	/* finally we can symlink it ... */
707 	ret = umsdos_symlink_x (dir, dentry, path, S_IFREG | 0777,UMSDOS_HLINK);
708 
709 out_unlock:
710 	/* remain locked for the call to notify_change ... */
711 	if (ret == 0) {
712 		struct iattr newattrs;
713 
714 		/* Do a real lookup to get the short name dentry */
715 		temp = umsdos_covered(olddentry->d_parent,
716 					old_info.fake.fname,
717 					old_info.fake.len);
718 		ret = PTR_ERR(temp);
719 		if (IS_ERR(temp))
720 			goto out_unlock2;
721 
722 		/* now resolve the link ... */
723 		temp = umsdos_solve_hlink(temp);
724 		ret = PTR_ERR(temp);
725 		if (IS_ERR(temp))
726 			goto out_unlock2;
727 
728 
729 #ifdef UMSDOS_PARANOIA
730 if (!oldinode->u.umsdos_i.i_is_hlink)
731 printk("UMSDOS_link: %s/%s, ino=%ld, not marked as hlink!\n",
732 olddentry->d_parent->d_name.name, olddentry->d_name.name, oldinode->i_ino);
733 #endif
734 		temp->d_inode->i_nlink++;
735 Printk(("UMSDOS_link: linked %s/%s, ino=%ld, nlink=%d\n",
736 olddentry->d_parent->d_name.name, olddentry->d_name.name,
737 oldinode->i_ino, oldinode->i_nlink));
738 		newattrs.ia_valid = 0;
739 		ret = umsdos_notify_change_locked(temp, &newattrs);
740  		if (ret == 0)
741 			mark_inode_dirty(temp->d_inode);
742 		dput(temp);
743 out_unlock2:
744 		if (ret == 0)
745 			mark_inode_dirty(olddentry->d_inode);
746 	}
747 	if (olddir != dir)
748 		up(&olddir->i_sem);
749 
750 out_free:
751 	free_page(buffer);
752 out:
753 	Printk (("umsdos_link %d\n", ret));
754 	return ret;
755 }
756 
757 
758 /*
759  * Add a sub-directory in a directory
760  */
761 /* #Specification: mkdir / Directory already exist in DOS
762  * We do the same thing as for file creation.
763  * For all user it is an error.
764  */
765 /* #Specification: mkdir / umsdos directory / create EMD
766  * When we created a new sub-directory in a UMSDOS
767  * directory (one with full UMSDOS semantics), we
768  * create immediately an EMD file in the new
769  * sub-directory so it inherits UMSDOS semantics.
770  */
UMSDOS_mkdir(struct inode * dir,struct dentry * dentry,int mode)771 int UMSDOS_mkdir (struct inode *dir, struct dentry *dentry, int mode)
772 {
773 	struct dentry *temp;
774 	struct inode *inode;
775 	int ret, err;
776 	struct umsdos_info info;
777 
778 	ret = umsdos_nevercreat (dir, dentry, -EEXIST);
779 	if (ret)
780 		goto out;
781 
782 	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
783 	if (ret)
784 		goto out;
785 
786 	info.entry.mode = mode | S_IFDIR;
787 	info.entry.rdev = 0;
788 	info.entry.uid = current->fsuid;
789 	info.entry.gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
790 	info.entry.ctime = info.entry.atime = info.entry.mtime = CURRENT_TIME;
791 	info.entry.flags = 0;
792 	info.entry.nlink = 1;
793 	ret = umsdos_newentry (dentry->d_parent, &info);
794 	if (ret)
795 		goto out;
796 
797 	/* lookup the short name dentry */
798 	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
799 	ret = PTR_ERR(temp);
800 	if (IS_ERR(temp))
801 		goto out_remove;
802 
803 	/* Make sure the short name doesn't exist */
804 	ret = -EEXIST;
805 	if (temp->d_inode) {
806 printk("umsdos_mkdir: short name %s/%s exists\n",
807 dentry->d_parent->d_name.name, info.fake.fname);
808 		goto out_remove_dput;
809 	}
810 
811 	ret = msdos_mkdir (dir, temp, mode);
812 	if (ret)
813 		goto out_remove_dput;
814 
815 	/*
816 	 * Lock the inode to protect the EMD creation ...
817 	 */
818 	inode = temp->d_inode;
819 	down(&inode->i_sem);
820 
821 	atomic_inc(&inode->i_count);
822 	d_instantiate(dentry, inode);
823 
824 	/* N.B. this should have an option to create the EMD ... */
825 	umsdos_lookup_patch_new(dentry, &info);
826 
827 	/*
828 	 * Create the EMD file, and set up the dir so it is
829 	 * promoted to EMD with the EMD file invisible.
830 	 *
831 	 * N.B. error return if EMD fails?
832 	 */
833 	err = umsdos_make_emd(dentry);
834 	umsdos_setup_dir(dentry);
835 
836 	up(&inode->i_sem);
837 	dput(temp);
838 
839 out:
840 	Printk(("umsdos_mkdir: %s/%s, ret=%d\n",
841 		dentry->d_parent->d_name.name, dentry->d_name.name, ret));
842 	return ret;
843 
844 	/* an error occurred ... remove EMD entry. */
845 out_remove_dput:
846 	dput(temp);
847 out_remove:
848 	umsdos_delentry (dentry->d_parent, &info, 1);
849 	goto out;
850 }
851 
852 /*
853  * Add a new device special file into a directory.
854  *
855  * #Specification: Special files / strategy
856  * Device special file, pipes, etc ... are created like normal
857  * file in the msdos file system. Of course they remain empty.
858  *
859  * One strategy was to create those files only in the EMD file
860  * since they were not important for MSDOS. The problem with
861  * that, is that there were not getting inode number allocated.
862  * The MSDOS filesystems is playing a nice game to fake inode
863  * number, so why not use it.
864  *
865  * The absence of inode number compatible with those allocated
866  * for ordinary files was causing major trouble with hard link
867  * in particular and other parts of the kernel I guess.
868  */
UMSDOS_mknod(struct inode * dir,struct dentry * dentry,int mode,int rdev)869 int UMSDOS_mknod (struct inode *dir, struct dentry *dentry,
870 		 int mode, int rdev)
871 {
872 	return umsdos_create_any (dir, dentry, mode, rdev, 0);
873 }
874 
875 /*
876  * Remove a sub-directory.
877  */
UMSDOS_rmdir(struct inode * dir,struct dentry * dentry)878 int UMSDOS_rmdir (struct inode *dir, struct dentry *dentry)
879 {
880 	struct dentry *temp;
881 	int ret, err, empty;
882 	struct umsdos_info info;
883 
884 	ret = umsdos_nevercreat (dir, dentry, -EPERM);
885 	if (ret)
886 		goto out;
887 
888 	ret = -EBUSY;
889 	if (!d_unhashed(dentry))
890 		goto out;
891 
892 	/* check whether the EMD is empty */
893 	ret = -ENOTEMPTY;
894 	empty = umsdos_isempty (dentry);
895 
896 	/* Have to remove the EMD file? */
897 	if (empty == 1) {
898 		struct dentry *demd;
899 
900 		demd = umsdos_get_emd_dentry(dentry);
901 		if (!IS_ERR(demd)) {
902 			err = -ENOENT;
903 			if (demd->d_inode)
904 				err = msdos_unlink (dentry->d_inode, demd);
905 Printk (("UMSDOS_rmdir: unlinking empty EMD err=%d", err));
906 #ifdef UMSDOS_PARANOIA
907 if (err)
908 printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n",
909 demd->d_parent->d_name.name, demd->d_name.name, err);
910 #endif
911 			if (!err) {
912 				d_delete(demd);
913 				ret = 0;
914 			}
915 			dput(demd);
916 		}
917 	} else if (empty == 2)
918 		ret = 0;
919 	if (ret)
920 		goto out;
921 
922 	umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
923 	/* Call findentry to complete the mangling */
924 	umsdos_findentry (dentry->d_parent, &info, 2);
925 	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
926 	ret = PTR_ERR(temp);
927 	if (IS_ERR(temp))
928 		goto out;
929 	/*
930 	 * Attempt to remove the msdos name.
931 	 */
932 	ret = msdos_rmdir (dir, temp);
933 	if (ret && ret != -ENOENT)
934 		goto out_dput;
935 
936 	d_delete(temp);
937 	/* OK so far ... remove the name from the EMD */
938 	ret = umsdos_delentry (dentry->d_parent, &info, 1);
939 #ifdef UMSDOS_PARANOIA
940 if (ret)
941 printk("umsdos_rmdir: delentry %s failed, ret=%d\n", info.entry.name, ret);
942 #endif
943 
944 	/* dput() temp if we didn't do it above */
945 out_dput:
946 	dput(temp);
947 
948 out:
949 	Printk (("umsdos_rmdir %d\n", ret));
950 	return ret;
951 }
952 
953 
954 /*
955  * Remove a file from the directory.
956  *
957  * #Specification: hard link / deleting a link
958  * When we delete a file and this file is a link,
959  * we must subtract 1 from the nlink field of the
960  * hidden link.
961  *
962  * If the count goes to 0, we delete this hidden
963  * link too.
964  */
UMSDOS_unlink(struct inode * dir,struct dentry * dentry)965 int UMSDOS_unlink (struct inode *dir, struct dentry *dentry)
966 {
967 	struct dentry *temp, *link = NULL;
968 	struct inode *inode;
969 	int ret;
970 	struct umsdos_info info;
971 
972 Printk(("UMSDOS_unlink: entering %s/%s\n",
973 dentry->d_parent->d_name.name, dentry->d_name.name));
974 
975 	ret = umsdos_nevercreat (dir, dentry, -EPERM);
976 	if (ret)
977 		goto out;
978 
979 	ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
980 	if (ret)
981 		goto out;
982 
983 	umsdos_lockcreate (dir);
984 	ret = umsdos_findentry (dentry->d_parent, &info, 1);
985 	if (ret) {
986 printk("UMSDOS_unlink: %s/%s not in EMD, ret=%d\n",
987 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
988 		goto out_unlock;
989 	}
990 
991 Printk (("UMSDOS_unlink %.*s ", info.fake.len, info.fake.fname));
992 
993 	/*
994 	 * Note! If this is a hardlink and the names are aliased,
995 	 * the short-name lookup will return the hardlink dentry.
996 	 * In order to get the correct (real) inode, we just drop
997 	 * the original dentry.
998 	 */
999 	if (info.entry.flags & UMSDOS_HLINK) {
1000 		d_drop(dentry);
1001 	}
1002 
1003 	/* Do a real lookup to get the short name dentry */
1004 	temp = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
1005 	ret = PTR_ERR(temp);
1006 	if (IS_ERR(temp))
1007 		goto out_unlock;
1008 
1009 	/*
1010 	 * Resolve hardlinks now, but defer processing until later.
1011 	 */
1012 	if (info.entry.flags & UMSDOS_HLINK) {
1013 		link = umsdos_solve_hlink(dget(temp));
1014 	}
1015 
1016 	/* Delete the EMD entry */
1017 	ret = umsdos_delentry (dentry->d_parent, &info, 0);
1018 	if (ret && ret != -ENOENT) {
1019 		printk(KERN_WARNING "UMSDOS_unlink: delentry %s, error=%d\n",
1020 			info.entry.name, ret);
1021 		goto out_dput;
1022 	}
1023 
1024 	ret = msdos_unlink(dir, temp);
1025 	if (!ret)
1026 		d_delete(temp);
1027 #ifdef UMSDOS_PARANOIA
1028 if (ret)
1029 printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n",
1030 temp->d_parent->d_name.name, temp->d_name.name, ret);
1031 #endif
1032 
1033 	/* dput() temp if we didn't do it above */
1034 out_dput:
1035 	dput(temp);
1036 
1037 out_unlock:
1038 	umsdos_unlockcreate (dir);
1039 
1040 	/*
1041 	 * Now check for deferred handling of a hardlink.
1042 	 */
1043 	if (!link)
1044 		goto out;
1045 
1046 	if (IS_ERR(link)) {
1047 printk("umsdos_unlink: failed to resolve %s/%s\n",
1048 dentry->d_parent->d_name.name, dentry->d_name.name);
1049 		if (!ret)
1050 			ret = PTR_ERR(link);
1051 		goto out;
1052 	}
1053 
1054 Printk(("umsdos_unlink: link %s/%s deferred, pending ret=%d\n",
1055 link->d_parent->d_name.name, link->d_name.name, ret));
1056 
1057 	/* already have an error? */
1058 	if (ret)
1059 		goto out_cleanup;
1060 
1061 	/* make sure the link exists ... */
1062 	inode = link->d_inode;
1063 	if (!inode) {
1064 		printk(KERN_WARNING "umsdos_unlink: hard link not found\n");
1065 		goto out_cleanup;
1066 	}
1067 
1068 	/*
1069 	 * If this was the last linked reference, delete it now.
1070 	 *
1071 	 * N.B. Deadlock problem? We should be holding the lock
1072 	 * for the hardlink's parent, but another process might
1073 	 * be holding that lock waiting for us to finish ...
1074 	 */
1075 	if (inode->i_nlink <= 1) {
1076 		ret = UMSDOS_unlink (link->d_parent->d_inode, link);
1077 		if (ret) {
1078 			printk(KERN_WARNING
1079 				"umsdos_unlink: link removal failed, ret=%d\n",
1080 				 ret);
1081 		} else
1082 			d_delete(link);
1083 	} else {
1084 		struct iattr newattrs;
1085 		inode->i_nlink--;
1086 		newattrs.ia_valid = 0;
1087 		ret = umsdos_notify_change_locked(link, &newattrs);
1088 		if (!ret)
1089 			mark_inode_dirty(link->d_inode);
1090 	}
1091 
1092 out_cleanup:
1093 	d_drop(link);
1094 	dput(link);
1095 
1096 out:
1097 	Printk (("umsdos_unlink %d\n", ret));
1098 	return ret;
1099 }
1100 
1101 /*
1102  * Rename (move) a file.
1103  */
UMSDOS_rename(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry)1104 int UMSDOS_rename (struct inode *old_dir, struct dentry *old_dentry,
1105 		   struct inode *new_dir, struct dentry *new_dentry)
1106 {
1107 	int ret;
1108 
1109 	ret = umsdos_nevercreat (new_dir, new_dentry, -EEXIST);
1110 	if (ret)
1111 		return ret;
1112 
1113 		/*
1114 		 * If the target already exists, delete it first.
1115 		 */
1116 	if (new_dentry->d_inode) {
1117 		dget(new_dentry);
1118 		if (S_ISDIR(old_dentry->d_inode->i_mode))
1119 			ret = UMSDOS_rmdir (new_dir, new_dentry);
1120 		else
1121 			ret = UMSDOS_unlink (new_dir, new_dentry);
1122 		if (!ret)
1123 			d_drop(new_dentry);
1124 		dput(new_dentry);
1125 		if (ret)
1126 			return ret;
1127 	}
1128 	ret = umsdos_rename_f(old_dir, old_dentry, new_dir, new_dentry, 0);
1129 	return ret;
1130 }
1131