OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [umsdos/] [rdir.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/slab.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
                                loff_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
/* only patch if needed (because we get called even for lookup
115
   (not only rlookup) stuff sometimes, like in umsdos_covered() */
116
                if (dentry->d_inode->u.umsdos_i.i_patched == 0)
117
                umsdos_patch_dentry_inode(dentry, 0);
118
 
119
        }
120
out:
121
        /* always install our dentry ops ... */
122
        dentry->d_op = &umsdos_dentry_operations;
123
        return ret;
124
}
125
 
126
 
127
struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry)
128
{
129
        return umsdos_rlookup_x (dir, dentry, 0);
130
}
131
 
132
 
133
/* #Specification: dual mode / rmdir in a DOS directory
134
 * In a DOS (not EMD in it) directory, we use a reverse strategy
135
 * compared with a UMSDOS directory. We assume that a subdirectory
136
 * of a DOS directory is also a DOS directory. This is not always
137
 * true (umssync may be used anywhere), but makes sense.
138
 *
139
 * So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
140
 * then we check if it is a Umsdos directory. We check if it is
141
 * really empty (only . .. and --linux-.--- in it). If it is true
142
 * we remove the EMD and do a msdos_rmdir() again.
143
 *
144
 * In a Umsdos directory, we assume all subdirectories are also
145
 * Umsdos directories, so we check the EMD file first.
146
 */
147
/* #Specification: pseudo root / rmdir /DOS
148
 * The pseudo sub-directory /DOS can't be removed!
149
 * This is done even if the pseudo root is not a Umsdos
150
 * directory anymore (very unlikely), but an accident (under
151
 * MS-DOS) is always possible.
152
 *
153
 * EPERM is returned.
154
 */
155
static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
156
{
157
        int ret, empty;
158
 
159
        ret = -EPERM;
160
        if (umsdos_is_pseudodos (dir, dentry))
161
                goto out;
162
 
163
        ret = -EBUSY;
164
        if (!d_unhashed(dentry))
165
                goto out;
166
 
167
        ret = msdos_rmdir (dir, dentry);
168
        if (ret != -ENOTEMPTY)
169
                goto out;
170
 
171
        empty = umsdos_isempty (dentry);
172
        if (empty == 1) {
173
                struct dentry *demd;
174
                /* We have to remove the EMD file. */
175
                demd = umsdos_get_emd_dentry(dentry);
176
                ret = PTR_ERR(demd);
177
                if (!IS_ERR(demd)) {
178
                        ret = 0;
179
                        if (demd->d_inode)
180
                                ret = msdos_unlink (dentry->d_inode, demd);
181
                        if (!ret)
182
                                d_delete(demd);
183
                        dput(demd);
184
                }
185
        }
186
        if (ret)
187
                goto out;
188
 
189
        /* now retry the original ... */
190
        ret = msdos_rmdir (dir, dentry);
191
 
192
out:
193
        return ret;
194
}
195
 
196
/* #Specification: dual mode / introduction
197
 * One goal of UMSDOS is to allow a practical and simple coexistence
198
 * between MS-DOS and Linux in a single partition. Using the EMD file
199
 * in each directory, UMSDOS adds Unix semantics and capabilities to
200
 * a normal DOS filesystem. To help and simplify coexistence, here is
201
 * the logic related to the EMD file.
202
 *
203
 * If it is missing, then the directory is managed by the MS-DOS driver.
204
 * The names are limited to DOS limits (8.3). No links, no device special
205
 * and pipe and so on.
206
 *
207
 * If it is there, it is the directory. If it is there but empty, then
208
 * the directory looks empty. The utility umssync allows synchronisation
209
 * of the real DOS directory and the EMD.
210
 *
211
 * Whenever umssync is applied to a directory without EMD, one is
212
 * created on the fly.  The directory is promoted to full Unix semantics.
213
 * Of course, the ls command will show exactly the same content as before
214
 * the umssync session.
215
 *
216
 * It is believed that the user/admin will promote directories to Unix
217
 * semantics as needed.
218
 *
219
 * The strategy to implement this is to use two function table (struct
220
 * inode_operations). One for true UMSDOS directory and one for directory
221
 * with missing EMD.
222
 *
223
 * Functions related to the DOS semantic (but aware of UMSDOS) generally
224
 * have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
225
 * from the one with full UMSDOS semantics.
226
 */
227
struct file_operations umsdos_rdir_operations =
228
{
229
        read:           generic_read_dir,
230
        readdir:        UMSDOS_rreaddir,
231
        ioctl:          UMSDOS_ioctl_dir,
232
};
233
 
234
struct inode_operations umsdos_rdir_inode_operations =
235
{
236
        create:         msdos_create,
237
        lookup:         UMSDOS_rlookup,
238
        unlink:         msdos_unlink,
239
        mkdir:          msdos_mkdir,
240
        rmdir:          UMSDOS_rrmdir,
241
        rename:         msdos_rename,
242
        setattr:        UMSDOS_notify_change,
243
};

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.