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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  linux/fs/umsdos/ioctl.c
3
 *
4
 *  Written 1993 by Jacques Gelinas
5
 *
6
 *  Extended MS-DOS ioctl directory handling functions
7
 */
8
 
9
#include <asm/segment.h>
10
#include <linux/errno.h>
11
#include <linux/mm.h>
12
#include <linux/kernel.h>
13
#include <linux/sched.h>
14
#include <linux/fs.h>
15
#include <linux/msdos_fs.h>
16
#include <linux/umsdos_fs.h>
17
 
18
#define PRINTK(x)
19
#define Printk(x) printk x
20
 
21
struct UMSDOS_DIR_ONCE {
22
        struct dirent *ent;
23
        int count;
24
};
25
 
26
/*
27
        Record a single entry the first call.
28
        Return -EINVAL the next one.
29
*/
30
static int umsdos_ioctl_fill(
31
        void * buf,
32
        const char * name,
33
        int name_len,
34
        off_t offset,
35
        ino_t ino)
36
{
37
        int ret = -EINVAL;
38
        struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *)buf;
39
        if (d->count == 0){
40
                memcpy_tofs (d->ent->d_name,name,name_len);
41
                put_user ('\0',d->ent->d_name+name_len);
42
                put_user (name_len,&d->ent->d_reclen);
43
                put_user (ino,&d->ent->d_ino);
44
                put_user (offset,&d->ent->d_off);
45
                d->count = 1;
46
                ret = 0;
47
        }
48
        return ret;
49
}
50
 
51
 
52
/*
53
        Perform special function on a directory
54
*/
55
int UMSDOS_ioctl_dir (
56
        struct inode *dir,
57
        struct file *filp,
58
        unsigned int cmd,
59
        unsigned long data)
60
{
61
        int ret = -EPERM;
62
        int err;
63
        /* #Specification: ioctl / acces
64
                Only root (effective id) is allowed to do IOCTL on directory
65
                in UMSDOS. EPERM is returned for other user.
66
        */
67
        /*
68
                Well, not all cases require write access, but it simplifies
69
                the code, and let's face it, there is only one client (umssync)
70
                for all this.
71
        */
72
        if ((err = verify_area(VERIFY_WRITE,(void*)data,sizeof(struct umsdos_ioctl))) < 0) {
73
                ret = err;
74
        }else if (current->euid == 0
75
                || cmd == UMSDOS_GETVERSION){
76
                struct umsdos_ioctl *idata = (struct umsdos_ioctl *)data;
77
                ret = -EINVAL;
78
                /* #Specification: ioctl / prototypes
79
                        The official prototype for the umsdos ioctl on directory
80
                        is:
81
 
82
                        int ioctl (
83
                                int fd,         // File handle of the directory
84
                                int cmd,        // command
85
                                struct umsdos_ioctl *data)
86
 
87
                        The struct and the commands are defined in linux/umsdos_fs.h.
88
 
89
                        umsdos_progs/umsdosio.c provide an interface in C++ to all
90
                        these ioctl. umsdos_progs/udosctl is a small utility showing
91
                        all this.
92
 
93
                        These ioctl generally allow one to work on the EMD or the
94
                        DOS directory independently. These are essential to implement
95
                        the synchronise.
96
                */
97
                PRINTK (("ioctl %d ",cmd));
98
                if (cmd == UMSDOS_GETVERSION){
99
                        /* #Specification: ioctl / UMSDOS_GETVERSION
100
                                The field version and release of the structure
101
                                umsdos_ioctl are filled with the version and release
102
                                number of the fs code in the kernel. This will allow
103
                                some form of checking. Users won't be able to run
104
                                incompatible utility such as the synchroniser (umssync).
105
                                umsdos_progs/umsdosio.c enforce this checking.
106
 
107
                                Return always 0.
108
                        */
109
                        put_fs_byte (UMSDOS_VERSION,&idata->version);
110
                        put_fs_byte (UMSDOS_RELEASE,&idata->release);
111
                        ret = 0;
112
                }else if (cmd == UMSDOS_READDIR_DOS){
113
                        /* #Specification: ioctl / UMSDOS_READDIR_DOS
114
                                One entry is read from the DOS directory at the current
115
                                file position. The entry is put as is in the dos_dirent
116
                                field of struct umsdos_ioctl.
117
 
118
                                Return > 0 if success.
119
                        */
120
                        struct UMSDOS_DIR_ONCE bufk;
121
                        bufk.count = 0;
122
                        bufk.ent = &idata->dos_dirent;
123
                        fat_readdir(dir,filp,&bufk,umsdos_ioctl_fill);
124
                        ret = bufk.count == 1 ? 1 : 0;
125
                }else if (cmd == UMSDOS_READDIR_EMD){
126
                        /* #Specification: ioctl / UMSDOS_READDIR_EMD
127
                                One entry is read from the EMD at the current
128
                                file position. The entry is put as is in the umsdos_dirent
129
                                field of struct umsdos_ioctl. The corresponding mangled
130
                                DOS entry name is put in the dos_dirent field.
131
 
132
                                All entries are read including hidden links. Blank
133
                                entries are skipped.
134
 
135
                                Return > 0 if success.
136
                        */
137
                        struct inode *emd_dir = umsdos_emd_dir_lookup (dir,0);
138
                        if (emd_dir != NULL){
139
                                while (1){
140
                                        if (filp->f_pos >= emd_dir->i_size){
141
                                                ret = 0;
142
                                                break;
143
                                        }else{
144
                                                struct umsdos_dirent entry;
145
                                                off_t f_pos = filp->f_pos;
146
                                                ret = umsdos_emd_dir_readentry (emd_dir,filp,&entry);
147
                                                if (ret < 0){
148
                                                        break;
149
                                                }else if (entry.name_len > 0){
150
                                                        struct umsdos_info info;
151
                                                        ret = entry.name_len;
152
                                                        umsdos_parse (entry.name,entry.name_len,&info);
153
                                                        info.f_pos = f_pos;
154
                                                        umsdos_manglename(&info);
155
                                                        memcpy_tofs(&idata->umsdos_dirent,&entry
156
                                                                ,sizeof(entry));
157
                                                        memcpy_tofs(&idata->dos_dirent.d_name
158
                                                                ,info.fake.fname,info.fake.len+1);
159
                                                        break;
160
                                                }
161
                                        }
162
                                }
163
                                iput (emd_dir);
164
                        }else{
165
                                /* The absence of the EMD is simply seen as an EOF */
166
                                ret = 0;
167
                        }
168
                }else if (cmd == UMSDOS_INIT_EMD){
169
                        /* #Specification: ioctl / UMSDOS_INIT_EMD
170
                                The UMSDOS_INIT_EMD command make sure the EMD
171
                                exist for a directory. If it does not, it is
172
                                created. Also, it makes sure the directory functions
173
                                table (struct inode_operations) is set to the UMSDOS
174
                                semantic. This mean that umssync may be applied to
175
                                an "opened" msdos directory, and it will change behavior
176
                                on the fly.
177
 
178
                                Return 0 if success.
179
                        */
180
                        extern struct inode_operations umsdos_rdir_inode_operations;
181
                        struct inode *emd_dir = umsdos_emd_dir_lookup (dir,1);
182
                        ret = emd_dir != NULL;
183
                        iput (emd_dir);
184
 
185
                        dir->i_op = ret
186
                                ? &umsdos_dir_inode_operations
187
                                : &umsdos_rdir_inode_operations;
188
                }else{
189
                        struct umsdos_ioctl data;
190
                        memcpy_fromfs (&data,idata,sizeof(data));
191
                        if (cmd == UMSDOS_CREAT_EMD){
192
                                /* #Specification: ioctl / UMSDOS_CREAT_EMD
193
                                        The umsdos_dirent field of the struct umsdos_ioctl is used
194
                                        as is to create a new entry in the EMD of the directory.
195
                                        The DOS directory is not modified.
196
                                        No validation is done (yet).
197
 
198
                                        Return 0 if success.
199
                                */
200
                                struct umsdos_info info;
201
                                /* This makes sure info.entry and info in general is correctly */
202
                                /* initialised */
203
                                memcpy (&info.entry,&data.umsdos_dirent
204
                                        ,sizeof(data.umsdos_dirent));
205
                                umsdos_parse (data.umsdos_dirent.name
206
                                        ,data.umsdos_dirent.name_len,&info);
207
                                ret = umsdos_newentry (dir,&info);
208
                        }else if (cmd == UMSDOS_RENAME_DOS){
209
                                /* #Specification: ioctl / UMSDOS_RENAME_DOS
210
                                        A file or directory is rename in a DOS directory
211
                                        (not moved across directory). The source name
212
                                        is in the dos_dirent.name field and the destination
213
                                        is in umsdos_dirent.name field.
214
 
215
                                        This ioctl allows umssync to rename a mangle file
216
                                        name before syncing it back in the EMD.
217
                                */
218
                                dir->i_count += 2;
219
                                ret = msdos_rename (dir
220
                                        ,data.dos_dirent.d_name,data.dos_dirent.d_reclen
221
                                        ,dir
222
                                        ,data.umsdos_dirent.name,data.umsdos_dirent.name_len,0);
223
                        }else if (cmd == UMSDOS_UNLINK_EMD){
224
                                /* #Specification: ioctl / UMSDOS_UNLINK_EMD
225
                                        The umsdos_dirent field of the struct umsdos_ioctl is used
226
                                        as is to remove an entry from the EMD of the directory.
227
                                        No validation is done (yet). The mode field is used
228
                                        to validate S_ISDIR or S_ISREG.
229
 
230
                                        Return 0 if success.
231
                                */
232
                                struct umsdos_info info;
233
                                /* This makes sure info.entry and info in general is correctly */
234
                                /* initialised */
235
                                memcpy (&info.entry,&data.umsdos_dirent
236
                                        ,sizeof(data.umsdos_dirent));
237
                                umsdos_parse (data.umsdos_dirent.name
238
                                        ,data.umsdos_dirent.name_len,&info);
239
                                ret = umsdos_delentry (dir,&info
240
                                        ,S_ISDIR(data.umsdos_dirent.mode));
241
                        }else if (cmd == UMSDOS_UNLINK_DOS){
242
                                /* #Specification: ioctl / UMSDOS_UNLINK_DOS
243
                                        The dos_dirent field of the struct umsdos_ioctl is used to
244
                                        execute a msdos_unlink operation. The d_name and d_reclen
245
                                        fields are used.
246
 
247
                                        Return 0 if success.
248
                                */
249
                                dir->i_count++;
250
                                ret = msdos_unlink (dir,data.dos_dirent.d_name
251
                                        ,data.dos_dirent.d_reclen);
252
                        }else if (cmd == UMSDOS_RMDIR_DOS){
253
                                /* #Specification: ioctl / UMSDOS_RMDIR_DOS
254
                                        The dos_dirent field of the struct umsdos_ioctl is used to
255
                                        execute a msdos_unlink operation. The d_name and d_reclen
256
                                        fields are used.
257
 
258
                                        Return 0 if success.
259
                                */
260
                                dir->i_count++;
261
                                ret = msdos_rmdir (dir,data.dos_dirent.d_name
262
                                        ,data.dos_dirent.d_reclen);
263
                        }else if (cmd == UMSDOS_STAT_DOS){
264
                                /* #Specification: ioctl / UMSDOS_STAT_DOS
265
                                        The dos_dirent field of the struct umsdos_ioctl is
266
                                        used to execute a stat operation in the DOS directory.
267
                                        The d_name and d_reclen fields are used.
268
 
269
                                        The following field of umsdos_ioctl.stat are filled.
270
 
271
                                        st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
272
                                        Return 0 if success.
273
                                */
274
                                struct inode *inode;
275
                                ret = umsdos_real_lookup (dir,data.dos_dirent.d_name
276
                                        ,data.dos_dirent.d_reclen,&inode);
277
                                if (ret == 0){
278
                                        data.stat.st_ino = inode->i_ino;
279
                                        data.stat.st_mode = inode->i_mode;
280
                                        data.stat.st_size = inode->i_size;
281
                                        data.stat.st_atime = inode->i_atime;
282
                                        data.stat.st_ctime = inode->i_ctime;
283
                                        data.stat.st_mtime = inode->i_mtime;
284
                                        memcpy_tofs (&idata->stat,&data.stat,sizeof(data.stat));
285
                                        iput (inode);
286
                                }
287
                        }else if (cmd == UMSDOS_DOS_SETUP){
288
                                /* #Specification: ioctl / UMSDOS_DOS_SETUP
289
                                        The UMSDOS_DOS_SETUP ioctl allow changing the
290
                                        default permission of the MsDOS file system driver
291
                                        on the fly. The MsDOS driver apply global permission
292
                                        to every file and directory. Normally these permissions
293
                                        are controlled by a mount option. This is not
294
                                        available for root partition, so a special utility
295
                                        (umssetup) is provided to do this, normally in
296
                                        /etc/rc.local.
297
 
298
                                        Be aware that this apply ONLY to MsDOS directory
299
                                        (those without EMD --linux-.---). Umsdos directory
300
                                        have independent (standard) permission for each
301
                                        and every file.
302
 
303
                                        The field umsdos_dirent provide the information needed.
304
                                        umsdos_dirent.uid and gid sets the owner and group.
305
                                        umsdos_dirent.mode set the permissions flags.
306
                                */
307
                                dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid;
308
                                dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid;
309
                                dir->i_sb->u.msdos_sb.options.fs_umask = data.umsdos_dirent.mode;
310
                                ret = 0;
311
                        }
312
                }
313
        }
314
        PRINTK (("ioctl return %d\n",ret));
315
        return ret;
316
}
317
 
318
 
319
 

powered by: WebSVN 2.1.0

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