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/sched.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/malloc.h>
19 #include <asm/uaccess.h>
22 #define Printk(x) printk x
25 extern struct inode
*pseudo_root
;
33 static int rdir_filldir (
41 struct RDIR_FILLDIR
*d
= (struct RDIR_FILLDIR
*) buf
;
43 PRINTK ((KERN_DEBUG
"rdir_filldir /mn/: entering\n"));
45 PRINTK ((KERN_DEBUG
"rdir_filldir /mn/: real root!\n"));
46 /* real root of a pseudo_rooted partition */
47 if (name_len
!= UMSDOS_PSDROOT_LEN
48 || memcmp (name
, UMSDOS_PSDROOT_NAME
, UMSDOS_PSDROOT_LEN
) != 0) {
49 /* So it is not the /linux directory */
53 /* Make sure the .. entry points back to the pseudo_root */
54 ino
= pseudo_root
->i_ino
;
56 ret
= d
->filldir (d
->dirbuf
, name
, name_len
, offset
, ino
);
59 /* Any DOS directory */
60 PRINTK ((KERN_DEBUG
"rdir_filldir /mn/: calling d->filldir (%p) for %.*s (%lu)\n", d
->filldir
, name_len
, name
, ino
));
61 ret
= d
->filldir (d
->dirbuf
, name
, name_len
, offset
, ino
);
67 static int UMSDOS_rreaddir (
72 struct RDIR_FILLDIR bufk
;
73 struct inode
*dir
= filp
->f_dentry
->d_inode
;
75 PRINTK ((KERN_DEBUG
"UMSDOS_rreaddir /mn/: entering %p %p\n", filldir
, dirbuf
));
78 bufk
.filldir
= filldir
;
80 bufk
.real_root
= pseudo_root
81 && dir
== iget (dir
->i_sb
, UMSDOS_ROOT_INO
)
82 && dir
== iget (pseudo_root
->i_sb
, UMSDOS_ROOT_INO
);
83 PRINTK ((KERN_DEBUG
"UMSDOS_rreaddir /mn/: calling fat_readdir with filldir=%p and exiting\n", filldir
));
84 return fat_readdir (filp
, &bufk
, rdir_filldir
);
89 * Lookup into a non promoted directory.
90 * If the result is a directory, make sure we find out if it is
91 * a promoted one or not (calling umsdos_setup_dir_inode(inode)).
93 int umsdos_rlookup_x (
95 struct dentry
*dentry
,
97 { /* Don't care about pseudo root mode */
98 /* so locating "linux" will work */
99 int len
= dentry
->d_name
.len
;
100 const char *name
= dentry
->d_name
.name
;
108 && dir
== iget (dir
->i_sb
, UMSDOS_ROOT_INO
)
109 && dir
== iget (pseudo_root
->i_sb
, UMSDOS_ROOT_INO
)) {
110 /* *result = pseudo_root; */
111 Printk ((KERN_WARNING
"umsdos_rlookup_x: we are at pseudo-root thingy?\n"));
112 inc_count (pseudo_root
);
114 /* #Specification: pseudo root / DOS/..
115 * In the real root directory (c:\), the directory ..
116 * is the pseudo root (c:\linux).
119 ret
= umsdos_real_lookup (dir
, dentry
);
120 inode
= dentry
->d_inode
;
123 Printk ((KERN_DEBUG
"umsdos_rlookup_x: umsdos_real_lookup for %.*s in %lu returned %d\n", len
, name
, dir
->i_ino
, ret
));
124 Printk ((KERN_DEBUG
"umsdos_rlookup_x: umsdos_real_lookup: inode is %p resolving to ", inode
));
125 if (inode
) { /* /mn/ FIXME: DEL_ME */
126 Printk ((KERN_DEBUG
"i_ino=%lu\n", inode
->i_ino
));
128 Printk ((KERN_DEBUG
"NONE!\n"));
132 if ((ret
== 0) && inode
) {
134 if (pseudo_root
&& inode
== pseudo_root
&& !nopseudo
) {
135 /* #Specification: pseudo root / DOS/linux
136 * Even in the real root directory (c:\), the directory
139 Printk ((KERN_WARNING
"umsdos_rlookup_x: do the pseudo-thingy...\n"));
141 iput (pseudo_root
); /* FIXME? */
143 } else if (S_ISDIR (inode
->i_mode
)) {
144 /* We must place the proper function table */
145 /* depending if this is a MsDOS directory or an UMSDOS directory */
146 Printk ((KERN_DEBUG
"umsdos_rlookup_x: setting up setup_dir_inode %lu...\n", inode
->i_ino
));
147 umsdos_setup_dir_inode (inode
);
151 iput (dir
); /* FIXME? */
152 PRINTK ((KERN_DEBUG
"umsdos_rlookup_x: returning %d\n", ret
));
159 struct dentry
*dentry
162 PRINTK ((KERN_DEBUG
"UMSDOS_rlookup /mn/: executing umsdos_rlookup_x for ino=%lu in %.*s\n", dir
->i_ino
, (int) dentry
->d_name
.len
, dentry
->d_name
.name
));
163 return umsdos_rlookup_x (dir
, dentry
, 0);
167 static int UMSDOS_rrmdir (
169 struct dentry
*dentry
)
171 /* #Specification: dual mode / rmdir in a DOS directory
172 * In a DOS (not EMD in it) directory, we use a reverse strategy
173 * compared with an Umsdos directory. We assume that a subdirectory
174 * of a DOS directory is also a DOS directory. This is not always
175 * true (umssync may be used anywhere), but make sense.
177 * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
178 * then we check if it is a Umsdos directory. We check if it is
179 * really empty (only . .. and --linux-.--- in it). If it is true
180 * we remove the EMD and do a msdos_rmdir() again.
182 * In a Umsdos directory, we assume all subdirectory are also
183 * Umsdos directory, so we check the EMD file first.
187 if (umsdos_is_pseudodos (dir
, dentry
)) {
188 /* #Specification: pseudo root / rmdir /DOS
189 * The pseudo sub-directory /DOS can't be removed!
190 * This is done even if the pseudo root is not a Umsdos
191 * directory anymore (very unlikely), but an accident (under
192 * MsDOS) is always possible.
198 umsdos_lockcreate (dir
);
200 ret
= msdos_rmdir (dir
, dentry
);
201 if (ret
== -ENOTEMPTY
) {
206 ret
= UMSDOS_rlookup (dir
, dentry
);
207 sdir
= dentry
->d_inode
;
208 PRINTK (("rrmdir lookup %d ", ret
));
212 if ((empty
= umsdos_isempty (sdir
)) != 0) {
213 PRINTK (("isempty %d i_count %d ", empty
,
214 atomic_read (&sdir
->i_count
)));
217 * Not a Umsdos directory, so the previous msdos_rmdir
221 } else if (empty
== 1) {
222 /* We have to removed the EMD file */
225 Printk ((KERN_WARNING
"UMSDOS_rmdir: hmmm... whatabout inode ? FIXME\n"));
226 temp
= creat_dentry (UMSDOS_EMD_FILE
, UMSDOS_EMD_NAMELEN
, NULL
, NULL
); /* FIXME: prolly should fill inode part ? */
227 ret
= msdos_unlink (sdir
, temp
);
231 ret
= msdos_rmdir (dir
, dentry
);
237 /* iput (sdir); FIXME */
240 umsdos_unlockcreate (dir
);
242 /* iput (dir); FIXME */
246 /* #Specification: dual mode / introduction
247 * One goal of UMSDOS is to allow a practical and simple coexistence
248 * between MsDOS and Linux in a single partition. Using the EMD file
249 * in each directory, UMSDOS add Unix semantics and capabilities to
250 * normal DOS file system. To help and simplify coexistence, here is
251 * the logic related to the EMD file.
253 * If it is missing, then the directory is managed by the MsDOS driver.
254 * The names are limited to DOS limits (8.3). No links, no device special
255 * and pipe and so on.
257 * If it is there, it is the directory. If it is there but empty, then
258 * the directory looks empty. The utility umssync allows synchronisation
259 * of the real DOS directory and the EMD.
261 * Whenever umssync is applied to a directory without EMD, one is
262 * created on the fly. The directory is promoted to full unix semantic.
263 * Of course, the ls command will show exactly the same content as before
264 * the umssync session.
266 * It is believed that the user/admin will promote directories to unix
267 * semantic as needed.
269 * The strategy to implement this is to use two function table (struct
270 * inode_operations). One for true UMSDOS directory and one for directory
273 * Functions related to the DOS semantic (but aware of UMSDOS) generally
274 * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
275 * from the one with full UMSDOS semantic.
277 static struct file_operations umsdos_rdir_operations
=
279 NULL
, /* lseek - default */
280 UMSDOS_dir_read
, /* read */
281 NULL
, /* write - bad */
282 UMSDOS_rreaddir
, /* readdir */
283 NULL
, /* poll - default */
284 UMSDOS_ioctl_dir
, /* ioctl - default */
286 NULL
, /* no special open code */
288 NULL
, /* no special release code */
292 struct inode_operations umsdos_rdir_inode_operations
=
294 &umsdos_rdir_operations
, /* default directory file-ops */
295 msdos_create
, /* create */
296 UMSDOS_rlookup
, /* lookup */
298 msdos_unlink
, /* unlink */
300 msdos_mkdir
, /* mkdir */
301 UMSDOS_rrmdir
, /* rmdir */
303 msdos_rename
, /* rename */
305 NULL
, /* followlink */
307 NULL
, /* writepage */
310 NULL
, /* permission */
312 NULL
, /* updatepage */
313 NULL
, /* revalidate */