2 * linux/fs/umsdos/rdir.c
4 * Written 1994 by Jacques Gelinas
6 * Extended MS-DOS directory pure MS-DOS handling functions
7 * (For directory without EMD file).
10 #include <linux/time.h>
12 #include <linux/msdos_fs.h>
13 #include <linux/errno.h>
14 #include <linux/stat.h>
15 #include <linux/limits.h>
16 #include <linux/umsdos_fs.h>
17 #include <linux/slab.h>
18 #include <linux/smp_lock.h>
20 #include <asm/uaccess.h>
23 extern struct dentry
*saved_root
;
24 extern struct inode
*pseudo_root
;
25 extern struct dentry_operations umsdos_dentry_operations
;
33 static int rdir_filldir ( void *buf
,
41 struct RDIR_FILLDIR
*d
= (struct RDIR_FILLDIR
*) buf
;
44 PRINTK ((KERN_DEBUG
"rdir_filldir /mn/: real root!\n"));
45 /* real root of a pseudo_rooted partition */
46 if (name_len
!= UMSDOS_PSDROOT_LEN
47 || memcmp (name
, UMSDOS_PSDROOT_NAME
, UMSDOS_PSDROOT_LEN
) != 0) {
48 /* So it is not the /linux directory */
49 if (name_len
== 2 && name
[0] == '.' && name
[1] == '.') {
50 /* Make sure the .. entry points back to the pseudo_root */
51 ino
= pseudo_root
->i_ino
;
53 ret
= d
->filldir (d
->dirbuf
, name
, name_len
, offset
, ino
, DT_UNKNOWN
);
56 /* Any DOS directory */
57 ret
= d
->filldir (d
->dirbuf
, name
, name_len
, offset
, ino
, DT_UNKNOWN
);
63 static int UMSDOS_rreaddir (struct file
*filp
, void *dirbuf
, filldir_t filldir
)
65 struct inode
*dir
= filp
->f_dentry
->d_inode
;
66 struct RDIR_FILLDIR bufk
;
70 bufk
.filldir
= filldir
;
72 bufk
.real_root
= pseudo_root
&& (dir
== saved_root
->d_inode
);
73 ret
= fat_readdir (filp
, &bufk
, rdir_filldir
);
80 * Lookup into a non promoted directory.
81 * If the result is a directory, make sure we find out if it is
82 * a promoted one or not (calling umsdos_setup_dir_inode(inode)).
84 /* #Specification: pseudo root / DOS/..
85 * In the real root directory (c:\), the directory ..
86 * is the pseudo root (c:\linux).
88 struct dentry
*umsdos_rlookup_x ( struct inode
*dir
, struct dentry
*dentry
, int nopseudo
)
92 if (saved_root
&& dir
== saved_root
->d_inode
&& !nopseudo
&&
93 dentry
->d_name
.len
== UMSDOS_PSDROOT_LEN
&&
94 memcmp (dentry
->d_name
.name
, UMSDOS_PSDROOT_NAME
, UMSDOS_PSDROOT_LEN
) == 0) {
95 /* #Specification: pseudo root / DOS/linux
96 * Even in the real root directory (c:\), the directory
100 ret
= ERR_PTR(-ENOENT
);
104 ret
= msdos_lookup (dir
, dentry
, NULL
);
107 "umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
108 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
,
112 if (dentry
->d_inode
) {
113 /* We must install the proper function table
114 * depending on whether this is an MS-DOS or
117 Printk ((KERN_DEBUG
"umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
118 dentry
->d_parent
->d_name
.name
, dentry
->d_name
.name
));
119 /* only patch if needed (because we get called even for lookup
120 (not only rlookup) stuff sometimes, like in umsdos_covered() */
121 if (UMSDOS_I(dentry
->d_inode
)->i_patched
== 0)
122 umsdos_patch_dentry_inode(dentry
, 0);
126 /* always install our dentry ops ... */
127 dentry
->d_op
= &umsdos_dentry_operations
;
132 struct dentry
*UMSDOS_rlookup ( struct inode
*dir
, struct dentry
*dentry
, struct nameidata
*nd
)
134 return umsdos_rlookup_x (dir
, dentry
, 0);
138 /* #Specification: dual mode / rmdir in a DOS directory
139 * In a DOS (not EMD in it) directory, we use a reverse strategy
140 * compared with a UMSDOS directory. We assume that a subdirectory
141 * of a DOS directory is also a DOS directory. This is not always
142 * true (umssync may be used anywhere), but makes sense.
144 * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
145 * then we check if it is a Umsdos directory. We check if it is
146 * really empty (only . .. and --linux-.--- in it). If it is true
147 * we remove the EMD and do a msdos_rmdir() again.
149 * In a Umsdos directory, we assume all subdirectories are also
150 * Umsdos directories, so we check the EMD file first.
152 /* #Specification: pseudo root / rmdir /DOS
153 * The pseudo sub-directory /DOS can't be removed!
154 * This is done even if the pseudo root is not a Umsdos
155 * directory anymore (very unlikely), but an accident (under
156 * MS-DOS) is always possible.
160 static int UMSDOS_rrmdir ( struct inode
*dir
, struct dentry
*dentry
)
165 if (umsdos_is_pseudodos (dir
, dentry
))
169 if (!d_unhashed(dentry
))
172 ret
= msdos_rmdir (dir
, dentry
);
173 if (ret
!= -ENOTEMPTY
)
176 empty
= umsdos_isempty (dentry
);
179 /* We have to remove the EMD file. */
180 demd
= umsdos_get_emd_dentry(dentry
);
185 ret
= msdos_unlink (dentry
->d_inode
, demd
);
194 /* now retry the original ... */
195 ret
= msdos_rmdir (dir
, dentry
);
201 /* #Specification: dual mode / introduction
202 * One goal of UMSDOS is to allow a practical and simple coexistence
203 * between MS-DOS and Linux in a single partition. Using the EMD file
204 * in each directory, UMSDOS adds Unix semantics and capabilities to
205 * a normal DOS filesystem. To help and simplify coexistence, here is
206 * the logic related to the EMD file.
208 * If it is missing, then the directory is managed by the MS-DOS driver.
209 * The names are limited to DOS limits (8.3). No links, no device special
210 * and pipe and so on.
212 * If it is there, it is the directory. If it is there but empty, then
213 * the directory looks empty. The utility umssync allows synchronisation
214 * of the real DOS directory and the EMD.
216 * Whenever umssync is applied to a directory without EMD, one is
217 * created on the fly. The directory is promoted to full Unix semantics.
218 * Of course, the ls command will show exactly the same content as before
219 * the umssync session.
221 * It is believed that the user/admin will promote directories to Unix
222 * semantics as needed.
224 * The strategy to implement this is to use two function table (struct
225 * inode_operations). One for true UMSDOS directory and one for directory
228 * Functions related to the DOS semantic (but aware of UMSDOS) generally
229 * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
230 * from the one with full UMSDOS semantics.
232 struct file_operations umsdos_rdir_operations
=
234 .read
= generic_read_dir
,
235 .readdir
= UMSDOS_rreaddir
,
236 .ioctl
= UMSDOS_ioctl_dir
,
239 struct inode_operations umsdos_rdir_inode_operations
=
241 .create
= msdos_create
,
242 .lookup
= UMSDOS_rlookup
,
243 .unlink
= msdos_unlink
,
244 .mkdir
= msdos_mkdir
,
245 .rmdir
= UMSDOS_rrmdir
,
246 .rename
= msdos_rename
,
247 .setattr
= UMSDOS_notify_change
,