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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [umsdos/] [rdir.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
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/segment.h>
20
 
21
#define PRINTK(x)
22
#define Printk(x) printk x
23
 
24
 
25
extern struct inode *pseudo_root;
26
 
27
struct RDIR_FILLDIR {
28
        void *dirbuf;
29
        filldir_t filldir;
30
        int real_root;
31
};
32
 
33
static int rdir_filldir(
34
        void * buf,
35
        const char * name,
36
        int name_len,
37
        off_t offset,
38
        ino_t ino)
39
{
40
        int ret = 0;
41
        struct RDIR_FILLDIR *d = (struct RDIR_FILLDIR*) buf;
42
        if (d->real_root){
43
                /* real root of a pseudo_rooted partition */
44
                if (name_len != UMSDOS_PSDROOT_LEN
45
                        || memcmp(name,UMSDOS_PSDROOT_NAME,UMSDOS_PSDROOT_LEN)!=0){
46
                        /* So it is not the /linux directory */
47
                        if (name_len == 2
48
                                && name[0] == '.'
49
                                && name[1] == '.'){
50
                                /* Make sure the .. entry points back to the pseudo_root */
51
                                ino = pseudo_root->i_ino;
52
                        }
53
                        ret = d->filldir (d->dirbuf,name,name_len,offset,ino);
54
                }
55
        }else{
56
                /* Any DOS directory */
57
                ret = d->filldir (d->dirbuf,name,name_len,offset,ino);
58
        }
59
        return ret;
60
}
61
 
62
 
63
static int UMSDOS_rreaddir (
64
        struct inode *dir,
65
        struct file *filp,
66
    void *dirbuf,
67
        filldir_t filldir)
68
{
69
        struct RDIR_FILLDIR bufk;
70
        bufk.filldir = filldir;
71
        bufk.dirbuf = dirbuf;
72
        bufk.real_root = pseudo_root != NULL
73
                && dir == dir->i_sb->s_mounted
74
                && dir == pseudo_root->i_sb->s_mounted;
75
        return fat_readdir(dir,filp,&bufk,rdir_filldir);
76
}
77
 
78
/*
79
        Lookup into a non promoted directory.
80
        If the result is a directory, make sure we find out if it is
81
        a promoted one or not (calling umsdos_setup_dir_inode(inode)).
82
*/
83
int umsdos_rlookup_x(
84
        struct inode *dir,
85
        const char *name,
86
        int len,
87
        struct inode **result,  /* Will hold inode of the file, if successful */
88
        int nopseudo)                   /* Don't care about pseudo root mode */
89
                                                        /* so locating "linux" will work */
90
{
91
        int ret;
92
        if (pseudo_root != NULL
93
                && len == 2
94
                && name[0] == '.'
95
                && name[1] == '.'
96
                && dir == dir->i_sb->s_mounted
97
                && dir == pseudo_root->i_sb->s_mounted){
98
                *result = pseudo_root;
99
                pseudo_root->i_count++;
100
                ret = 0;
101
                /* #Specification: pseudo root / DOS/..
102
                        In the real root directory (c:\), the directory ..
103
                        is the pseudo root (c:\linux).
104
                */
105
        }else{
106
                ret = umsdos_real_lookup (dir,name,len,result);
107
                if (ret == 0){
108
                        struct inode *inode = *result;
109
                        if (inode == pseudo_root && !nopseudo){
110
                                /* #Specification: pseudo root / DOS/linux
111
                                        Even in the real root directory (c:\), the directory
112
                                        /linux won't show
113
                                */
114
                                ret = -ENOENT;
115
                                iput (pseudo_root);
116
                                *result = NULL;
117
                        }else if (S_ISDIR(inode->i_mode)){
118
                                /* We must place the proper function table */
119
                                /* depending if this is a MsDOS directory or an UMSDOS directory */
120
                                umsdos_setup_dir_inode(inode);
121
                        }
122
                }
123
        }
124
        iput (dir);
125
        return ret;
126
}
127
int UMSDOS_rlookup(
128
        struct inode *dir,
129
        const char *name,
130
        int len,
131
        struct inode **result)  /* Will hold inode of the file, if successful */
132
{
133
        return umsdos_rlookup_x(dir,name,len,result,0);
134
}
135
 
136
static int UMSDOS_rrmdir (
137
        struct inode *dir,
138
        const char *name,
139
        int len)
140
{
141
        /* #Specification: dual mode / rmdir in a DOS directory
142
                In a DOS (not EMD in it) directory, we use a reverse strategy
143
                compared with an Umsdos directory. We assume that a subdirectory
144
                of a DOS directory is also a DOS directory. This is not always
145
                true (umssync may be used anywhere), but make sense.
146
 
147
                So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
148
                then we check if it is a Umsdos directory. We check if it is
149
                really empty (only . .. and --linux-.--- in it). If it is true
150
                we remove the EMD and do a msdos_rmdir() again.
151
 
152
                In a Umsdos directory, we assume all subdirectory are also
153
                Umsdos directory, so we check the EMD file first.
154
        */
155
        int ret;
156
        if (umsdos_is_pseudodos(dir,name,len)){
157
                /* #Specification: pseudo root / rmdir /DOS
158
                        The pseudo sub-directory /DOS can't be removed!
159
                        This is done even if the pseudo root is not a Umsdos
160
                        directory anymore (very unlikely), but an accident (under
161
                        MsDOS) is always possible.
162
 
163
                        EPERM is returned.
164
                */
165
                ret = -EPERM;
166
        }else{
167
                umsdos_lockcreate (dir);
168
                dir->i_count++;
169
                ret = msdos_rmdir (dir,name,len);
170
                if (ret == -ENOTEMPTY){
171
                        struct inode *sdir;
172
                        dir->i_count++;
173
                        ret = UMSDOS_rlookup (dir,name,len,&sdir);
174
                        PRINTK (("rrmdir lookup %d ",ret));
175
                        if (ret == 0){
176
                                int empty;
177
                                if ((empty = umsdos_isempty (sdir)) != 0){
178
                                        PRINTK (("isempty %d i_count %ld ",empty,sdir->i_count));
179
                                        if (empty == 2){
180
                                                /*
181
                                                        Not a Umsdos directory, so the previous msdos_rmdir
182
                                                        was not lying :-)
183
                                                */
184
                                                ret = -ENOTEMPTY;
185
                                        }else if (empty == 1){
186
                                                /* We have to removed the EMD file */
187
                                                ret = msdos_unlink(sdir,UMSDOS_EMD_FILE
188
                                                        ,UMSDOS_EMD_NAMELEN);
189
                                                sdir = NULL;
190
                                                if (ret == 0){
191
                                                        dir->i_count++;
192
                                                        ret = msdos_rmdir (dir,name,len);
193
                                                }
194
                                        }
195
                                }else{
196
                                        ret = -ENOTEMPTY;
197
                                }
198
                                iput (sdir);
199
                        }
200
                }
201
                umsdos_unlockcreate (dir);
202
        }
203
        iput (dir);
204
        return ret;
205
}
206
 
207
/* #Specification: dual mode / introduction
208
        One goal of UMSDOS is to allow a practical and simple coexistence
209
        between MsDOS and Linux in a single partition. Using the EMD file
210
        in each directory, UMSDOS add Unix semantics and capabilities to
211
        normal DOS file system. To help and simplify coexistence, here is
212
        the logic related to the EMD file.
213
 
214
        If it is missing, then the directory is managed by the MsDOS driver.
215
        The names are limited to DOS limits (8.3). No links, no device special
216
        and pipe and so on.
217
 
218
        If it is there, it is the directory. If it is there but empty, then
219
        the directory looks empty. The utility umssync allows synchronisation
220
        of the real DOS directory and the EMD.
221
 
222
        Whenever umssync is applied to a directory without EMD, one is
223
        created on the fly. The directory is promoted to full unix semantic.
224
        Of course, the ls command will show exactly the same content as before
225
        the umssync session.
226
 
227
        It is believed that the user/admin will promote directories to unix
228
        semantic as needed.
229
 
230
        The strategy to implement this is to use two function table (struct
231
        inode_operations). One for true UMSDOS directory and one for directory
232
        with missing EMD.
233
 
234
        Functions related to the DOS semantic (but aware of UMSDOS) generally
235
        have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
236
        from the one with full UMSDOS semantic.
237
*/
238
static struct file_operations umsdos_rdir_operations = {
239
        NULL,                           /* lseek - default */
240
        UMSDOS_dir_read,        /* read */
241
        NULL,                           /* write - bad */
242
        UMSDOS_rreaddir,        /* readdir */
243
        NULL,                           /* select - default */
244
        UMSDOS_ioctl_dir,       /* ioctl - default */
245
        NULL,                           /* mmap */
246
        NULL,                           /* no special open code */
247
        NULL,                           /* no special release code */
248
        NULL                            /* fsync */
249
};
250
 
251
struct inode_operations umsdos_rdir_inode_operations = {
252
        &umsdos_rdir_operations,        /* default directory file-ops */
253
        msdos_create,           /* create */
254
        UMSDOS_rlookup,         /* lookup */
255
        NULL,                           /* link */
256
        msdos_unlink,           /* unlink */
257
        NULL,                           /* symlink */
258
        msdos_mkdir,            /* mkdir */
259
        UMSDOS_rrmdir,          /* rmdir */
260
        NULL,                           /* mknod */
261
        msdos_rename,           /* rename */
262
        NULL,                           /* readlink */
263
        NULL,                           /* follow_link */
264
        NULL,                           /* readpage */
265
        NULL,                           /* writepage */
266
        NULL,                           /* bmap */
267
        NULL,                           /* truncate */
268
        NULL                            /* permission */
269
};
270
 
271
 

powered by: WebSVN 2.1.0

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