~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/umsdos/rdir.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  linux/fs/umsdos/rdir.c
  3  *
  4  *  Written 1994 by Jacques Gelinas
  5  *
  6  *  Extended MS-DOS directory pure MS-DOS handling functions
  7  *  (For directory without EMD file).
  8  */
  9 
 10 #include <linux/sched.h>
 11 #include <linux/fs.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>
 18 
 19 #include <asm/uaccess.h>
 20 
 21 
 22 extern struct dentry *saved_root;
 23 extern struct inode *pseudo_root;
 24 extern struct dentry_operations umsdos_dentry_operations;
 25 
 26 struct RDIR_FILLDIR {
 27         void *dirbuf;
 28         filldir_t filldir;
 29         int real_root;
 30 };
 31 
 32 static int rdir_filldir (       void *buf,
 33                                 const char *name,
 34                                 int name_len,
 35                                 off_t offset,
 36                                 ino_t ino,
 37                                 unsigned int d_type)
 38 {
 39         int ret = 0;
 40         struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR *) buf;
 41 
 42         if (d->real_root) {
 43                 PRINTK ((KERN_DEBUG "rdir_filldir /mn/: real root!\n"));
 44                 /* real root of a pseudo_rooted partition */
 45                 if (name_len != UMSDOS_PSDROOT_LEN
 46                     || memcmp (name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) != 0) {
 47                         /* So it is not the /linux directory */
 48                         if (name_len == 2 && name[0] == '.' && name[1] == '.') {
 49                                 /* Make sure the .. entry points back to the pseudo_root */
 50                                 ino = pseudo_root->i_ino;
 51                         }
 52                         ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN);
 53                 }
 54         } else {
 55                 /* Any DOS directory */
 56                 ret = d->filldir (d->dirbuf, name, name_len, offset, ino, DT_UNKNOWN);
 57         }
 58         return ret;
 59 }
 60 
 61 
 62 static int UMSDOS_rreaddir (struct file *filp, void *dirbuf, filldir_t filldir)
 63 {
 64         struct inode *dir = filp->f_dentry->d_inode;
 65         struct RDIR_FILLDIR bufk;
 66 
 67         bufk.filldir = filldir;
 68         bufk.dirbuf = dirbuf;
 69         bufk.real_root = pseudo_root && (dir == saved_root->d_inode);
 70         return fat_readdir (filp, &bufk, rdir_filldir);
 71 }
 72 
 73 
 74 /*
 75  * Lookup into a non promoted directory.
 76  * If the result is a directory, make sure we find out if it is
 77  * a promoted one or not (calling umsdos_setup_dir_inode(inode)).
 78  */
 79 /* #Specification: pseudo root / DOS/..
 80  * In the real root directory (c:\), the directory ..
 81  * is the pseudo root (c:\linux).
 82  */
 83 struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo)
 84 {
 85         struct dentry *ret;
 86 
 87         if (saved_root && dir == saved_root->d_inode && !nopseudo &&
 88             dentry->d_name.len == UMSDOS_PSDROOT_LEN &&
 89             memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) {
 90                 /* #Specification: pseudo root / DOS/linux
 91                  * Even in the real root directory (c:\), the directory
 92                  * /linux won't show
 93                  */
 94                  
 95                 ret = ERR_PTR(-ENOENT);
 96                 goto out;
 97         }
 98 
 99         ret = msdos_lookup (dir, dentry);
100         if (ret) {
101                 printk(KERN_WARNING
102                         "umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
103                         dentry->d_parent->d_name.name, dentry->d_name.name,
104                         PTR_ERR(ret));
105                 goto out;
106         }
107         if (dentry->d_inode) {
108                 /* We must install the proper function table
109                  * depending on whether this is an MS-DOS or 
110                  * a UMSDOS directory
111                  */
112 Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
113 dentry->d_parent->d_name.name, dentry->d_name.name));
114                 umsdos_patch_dentry_inode(dentry, 0);
115 
116         }
117 out:
118         /* always install our dentry ops ... */
119         dentry->d_op = &umsdos_dentry_operations;
120         return ret;
121 }
122 
123 
124 struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry)
125 {
126         return umsdos_rlookup_x (dir, dentry, 0);
127 }
128 
129 
130 /* #Specification: dual mode / rmdir in a DOS directory
131  * In a DOS (not EMD in it) directory, we use a reverse strategy
132  * compared with a UMSDOS directory. We assume that a subdirectory
133  * of a DOS directory is also a DOS directory. This is not always
134  * true (umssync may be used anywhere), but makes sense.
135  * 
136  * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
137  * then we check if it is a Umsdos directory. We check if it is
138  * really empty (only . .. and --linux-.--- in it). If it is true
139  * we remove the EMD and do a msdos_rmdir() again.
140  * 
141  * In a Umsdos directory, we assume all subdirectories are also
142  * Umsdos directories, so we check the EMD file first.
143  */
144 /* #Specification: pseudo root / rmdir /DOS
145  * The pseudo sub-directory /DOS can't be removed!
146  * This is done even if the pseudo root is not a Umsdos
147  * directory anymore (very unlikely), but an accident (under
148  * MS-DOS) is always possible.
149  * 
150  * EPERM is returned.
151  */
152 static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
153 {
154         int ret, empty;
155 
156         ret = -EPERM;
157         if (umsdos_is_pseudodos (dir, dentry))
158                 goto out;
159 
160         ret = -EBUSY;
161         if (!d_unhashed(dentry))
162                 goto out;
163 
164         ret = msdos_rmdir (dir, dentry);
165         if (ret != -ENOTEMPTY)
166                 goto out;
167 
168         empty = umsdos_isempty (dentry);
169         if (empty == 1) {
170                 struct dentry *demd;
171                 /* We have to remove the EMD file. */
172                 demd = umsdos_get_emd_dentry(dentry);
173                 ret = PTR_ERR(demd);
174                 if (!IS_ERR(demd)) {
175                         ret = 0;
176                         if (demd->d_inode)
177                                 ret = msdos_unlink (dentry->d_inode, demd);
178                         if (!ret)
179                                 d_delete(demd);
180                         dput(demd);
181                 }
182         }
183         if (ret)
184                 goto out;
185 
186         /* now retry the original ... */
187         ret = msdos_rmdir (dir, dentry);
188 
189 out:
190         return ret;
191 }
192 
193 /* #Specification: dual mode / introduction
194  * One goal of UMSDOS is to allow a practical and simple coexistence
195  * between MS-DOS and Linux in a single partition. Using the EMD file
196  * in each directory, UMSDOS adds Unix semantics and capabilities to
197  * a normal DOS filesystem. To help and simplify coexistence, here is
198  * the logic related to the EMD file.
199  * 
200  * If it is missing, then the directory is managed by the MS-DOS driver.
201  * The names are limited to DOS limits (8.3). No links, no device special
202  * and pipe and so on.
203  * 
204  * If it is there, it is the directory. If it is there but empty, then
205  * the directory looks empty. The utility umssync allows synchronisation
206  * of the real DOS directory and the EMD.
207  * 
208  * Whenever umssync is applied to a directory without EMD, one is
209  * created on the fly.  The directory is promoted to full Unix semantics.
210  * Of course, the ls command will show exactly the same content as before
211  * the umssync session.
212  * 
213  * It is believed that the user/admin will promote directories to Unix
214  * semantics as needed.
215  * 
216  * The strategy to implement this is to use two function table (struct
217  * inode_operations). One for true UMSDOS directory and one for directory
218  * with missing EMD.
219  * 
220  * Functions related to the DOS semantic (but aware of UMSDOS) generally
221  * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
222  * from the one with full UMSDOS semantics.
223  */
224 struct file_operations umsdos_rdir_operations =
225 {
226         read:           generic_read_dir,
227         readdir:        UMSDOS_rreaddir,
228         ioctl:          UMSDOS_ioctl_dir,
229 };
230 
231 struct inode_operations umsdos_rdir_inode_operations =
232 {
233         create:         msdos_create,
234         lookup:         UMSDOS_rlookup,
235         unlink:         msdos_unlink,
236         mkdir:          msdos_mkdir,
237         rmdir:          UMSDOS_rrmdir,
238         rename:         msdos_rename,
239         setattr:        UMSDOS_notify_change,
240 };
241 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.