This source file includes following definitions.
- umsdos_readdir_kmem
- umsdos_file_read_kmem
- umsdos_file_write_kmem
- umsdos_emd_dir_write
- umsdos_emd_dir_read
- umsdos_emd_dir_lookup
- umsdos_emd_dir_readentry
- umsdos_writeentry
- umsdos_fillbuf
- umsdos_find
- umsdos_newentry
- umsdos_newhidden
- umsdos_delentry
- umsdos_isempty
- umsdos_findentry
1
2
3
4
5
6
7
8 #include <linux/types.h>
9 #include <linux/fcntl.h>
10 #include <linux/kernel.h>
11 #include <asm/segment.h>
12 #include <linux/sched.h>
13 #include <linux/errno.h>
14 #include <linux/string.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 int umsdos_readdir_kmem(
22 struct inode *inode,
23 struct file *filp,
24 struct dirent *dirent,
25 int count)
26 {
27 int ret;
28 int old_fs = get_fs();
29 set_fs (KERNEL_DS);
30 ret = msdos_readdir(inode,filp,dirent,count);
31 set_fs (old_fs);
32 return ret;
33 }
34
35
36
37 int umsdos_file_read_kmem(
38 struct inode *inode,
39 struct file *filp,
40 char *buf,
41 int count)
42 {
43 int ret;
44 int old_fs = get_fs();
45 set_fs (KERNEL_DS);
46 ret = msdos_file_read(inode,filp,buf,count);
47 set_fs (old_fs);
48 return ret;
49 }
50
51
52
53 int umsdos_file_write_kmem(
54 struct inode *inode,
55 struct file *filp,
56 char *buf,
57 int count)
58 {
59 int ret;
60 int old_fs = get_fs();
61 set_fs (KERNEL_DS);
62 ret = msdos_file_write(inode,filp,buf,count);
63 set_fs (old_fs);
64 return ret;
65 }
66
67
68
69
70
71
72
73
74 int umsdos_emd_dir_write (
75 struct inode *emd_dir,
76 struct file *filp,
77 char *buf,
78 int count)
79 {
80 int written;
81 filp->f_flags = 0;
82 written = umsdos_file_write_kmem (emd_dir,filp,buf,count);
83 return written != count ? -EIO : 0;
84 }
85
86
87
88
89
90 int umsdos_emd_dir_read (
91 struct inode *emd_dir,
92 struct file *filp,
93 char *buf,
94 int count)
95 {
96 int ret = 0;
97 int sizeread;
98 filp->f_flags = 0;
99 sizeread = umsdos_file_read_kmem (emd_dir,filp,buf,count);
100 if (sizeread != count){
101 printk ("UMSDOS: problem with EMD file. Can't read\n");
102 ret = -EIO;
103 }
104 return ret;
105
106 }
107
108
109
110
111
112 struct inode *umsdos_emd_dir_lookup(struct inode *dir, int creat)
113 {
114 struct inode *ret = NULL;
115 if (dir->u.umsdos_i.i_emd_dir != 0){
116 ret = iget (dir->i_sb,dir->u.umsdos_i.i_emd_dir);
117 PRINTK (("deja trouve %d %x [%d] "
118 ,dir->u.umsdos_i.i_emd_dir,ret,ret->i_count));
119 }else{
120 umsdos_real_lookup (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN,&ret);
121 PRINTK (("emd_dir_lookup "));
122 if (ret != NULL){
123 PRINTK (("Find --linux "));
124 dir->u.umsdos_i.i_emd_dir = ret->i_ino;
125 }else if (creat){
126 int code;
127 PRINTK (("avant create "));
128 dir->i_count++;
129 code = msdos_create (dir,UMSDOS_EMD_FILE,UMSDOS_EMD_NAMELEN
130 ,S_IFREG|0777,&ret);
131 PRINTK (("Creat EMD code %d ret %x ",code,ret));
132 if (ret != NULL){
133 dir->u.umsdos_i.i_emd_dir = ret->i_ino;
134 }else{
135 printk ("UMSDOS: Can't create EMD file\n");
136 }
137 }
138 }
139 if (ret != NULL){
140
141 ret->u.umsdos_i.i_emd_owner = 0xffffffff;
142 }
143 return ret;
144 }
145
146
147
148
149
150
151 int umsdos_emd_dir_readentry (
152 struct inode *emd_dir,
153 struct file *filp,
154 struct umsdos_dirent *entry)
155 {
156 int ret = umsdos_emd_dir_read(emd_dir,filp,(char*)entry,UMSDOS_REC_SIZE);
157 if (ret == 0){
158
159 int recsize = umsdos_evalrecsize (entry->name_len);
160 if (recsize > UMSDOS_REC_SIZE){
161 ret = umsdos_emd_dir_read(emd_dir,filp
162 ,((char*)entry)+UMSDOS_REC_SIZE,recsize - UMSDOS_REC_SIZE);
163
164 }
165 }
166 return ret;
167 }
168
169
170
171
172 int umsdos_writeentry (
173 struct inode *dir,
174 struct inode *emd_dir,
175 struct umsdos_info *info,
176 int free_entry)
177 {
178 int ret = 0;
179 struct file filp;
180 struct umsdos_dirent *entry = &info->entry;
181 struct umsdos_dirent entry0;
182 if (free_entry){
183
184
185
186
187
188
189 memset (&entry0,0,sizeof(entry0));
190 entry = &entry0;
191 }else if (entry->name_len > 0){
192 memset (entry->name+entry->name_len,'\0'
193 ,sizeof(entry->name)-entry->name_len);
194
195
196
197
198
199
200 memset (entry->spare,0,sizeof(entry->spare));
201 }
202 filp.f_pos = info->f_pos;
203 filp.f_reada = 0;
204 ret = umsdos_emd_dir_write(emd_dir,&filp,(char*)entry,info->recsize);
205 if (ret != 0){
206 printk ("UMSDOS: problem with EMD file. Can't write\n");
207 }else{
208 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
209 dir->i_dirt = 1;
210 }
211 return ret;
212 }
213
214 #define CHUNK_SIZE (8*UMSDOS_REC_SIZE)
215 struct find_buffer{
216 char buffer[CHUNK_SIZE];
217 int pos;
218 int size;
219 struct file filp;
220 };
221
222
223
224
225
226
227
228 static int umsdos_fillbuf (
229 struct inode *inode,
230 struct find_buffer *buf)
231 {
232 int ret = -ENOENT;
233 int mustmove = buf->size - buf->pos;
234 int mustread;
235 int remain;
236 if (mustmove > 0){
237 memcpy (buf->buffer,buf->buffer+buf->pos,mustmove);
238 }
239 buf->pos = 0;
240 mustread = CHUNK_SIZE - mustmove;
241 remain = inode->i_size - buf->filp.f_pos;
242 if (remain < mustread) mustread = remain;
243 if (mustread > 0){
244 ret = umsdos_emd_dir_read (inode,&buf->filp,buf->buffer+mustmove
245 ,mustread);
246 if (ret == 0) buf->size = mustmove + mustread;
247 }else if (mustmove){
248 buf->size = mustmove;
249 ret = 0;
250 }
251 return ret;
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 static int umsdos_find (
276 struct inode *dir,
277 struct umsdos_info *info,
278
279 struct inode **pt_emd_dir)
280
281 {
282
283
284
285
286
287 int ret = -ENOENT;
288 struct inode *emd_dir = umsdos_emd_dir_lookup(dir,1);
289 if (emd_dir != NULL){
290 struct umsdos_dirent *entry = &info->entry;
291 int recsize = info->recsize;
292 struct {
293 off_t posok;
294 int found;
295 off_t one;
296 int onesize;
297 }empty;
298
299 struct find_buffer buf;
300 buf.pos = 0;
301 buf.size = 0;
302 buf.filp.f_pos = 0;
303 buf.filp.f_reada = 1;
304 empty.found = 0;
305 empty.posok = emd_dir->i_size;
306 empty.onesize = 0;
307 while (1){
308 struct umsdos_dirent *rentry = (struct umsdos_dirent*)
309 (buf.buffer + buf.pos);
310 int file_pos = buf.filp.f_pos - buf.size + buf.pos;
311 if (buf.pos == buf.size){
312 ret = umsdos_fillbuf (emd_dir,&buf);
313 if (ret < 0){
314
315 info->f_pos = empty.posok;
316 break;
317 }
318 }else if (rentry->name_len == 0){
319
320
321 if (entry->name_len == 0){
322 info->f_pos = file_pos;
323 ret = 0;
324 break;
325 }else if (!empty.found){
326 if (empty.onesize == 0){
327
328 empty.one = file_pos;
329 }
330
331 empty.onesize += UMSDOS_REC_SIZE;
332 if (empty.onesize == recsize){
333
334 empty.posok = empty.one;
335 empty.found = 1;
336 }
337 }
338 buf.pos += UMSDOS_REC_SIZE;
339 }else{
340 int entry_size = umsdos_evalrecsize(rentry->name_len);
341 if (buf.pos+entry_size > buf.size){
342 ret = umsdos_fillbuf (emd_dir,&buf);
343 if (ret < 0){
344
345 info->f_pos = empty.posok;
346 break;
347 }
348 }else{
349 empty.onesize = 0;
350 if (entry->name_len == rentry->name_len
351 && memcmp(entry->name,rentry->name,rentry->name_len)
352 ==0){
353 info->f_pos = file_pos;
354 *entry = *rentry;
355 ret = 0;
356 break;
357 }else{
358 buf.pos += entry_size;
359 }
360 }
361 }
362 }
363 umsdos_manglename(info);
364 }
365 *pt_emd_dir = emd_dir;
366 return ret;
367 }
368
369
370
371
372
373
374
375 int umsdos_newentry (
376 struct inode *dir,
377 struct umsdos_info *info)
378 {
379 struct inode *emd_dir;
380 int ret = umsdos_find (dir,info,&emd_dir);
381 if (ret == 0){
382 ret = -EEXIST;
383 }else if (ret == -ENOENT){
384 ret = umsdos_writeentry(dir,emd_dir,info,0);
385 PRINTK (("umsdos_newentry EDM ret = %d\n",ret));
386 }
387 iput (emd_dir);
388 return ret;
389 }
390
391
392
393
394 int umsdos_newhidden (
395 struct inode *dir,
396 struct umsdos_info *info)
397 {
398 struct inode *emd_dir;
399 int ret;
400 umsdos_parse ("..LINK",6,info);
401 info->entry.name_len = 0;
402 ret = umsdos_find (dir,info,&emd_dir);
403 iput (emd_dir);
404 if (ret == -ENOENT || ret == 0){
405
406
407
408
409
410 info->entry.name_len = sprintf (info->entry.name,"..LINK%ld"
411 ,info->f_pos);
412 ret = 0;
413 }
414 return ret;
415 }
416
417
418
419
420
421
422 int umsdos_delentry (
423 struct inode *dir,
424 struct umsdos_info *info,
425 int isdir)
426 {
427 struct inode *emd_dir;
428 int ret = umsdos_find (dir,info,&emd_dir);
429 if (ret == 0){
430 if (info->entry.name_len != 0){
431 if ((isdir != 0) != (S_ISDIR(info->entry.mode) != 0)){
432 if (S_ISDIR(info->entry.mode)){
433 ret = -EISDIR;
434 }else{
435 ret = -ENOTDIR;
436 }
437 }else{
438 ret = umsdos_writeentry(dir,emd_dir,info,1);
439 }
440 }
441 }
442 iput(emd_dir);
443 return ret;
444 }
445
446
447
448
449
450
451
452
453 int umsdos_isempty (struct inode *dir)
454 {
455 int ret = 2;
456 struct inode *emd_dir = umsdos_emd_dir_lookup(dir,0);
457
458 if (emd_dir != NULL){
459 struct file filp;
460
461 filp.f_pos = 0;
462 filp.f_reada = 1;
463 filp.f_flags = O_RDONLY;
464 ret = 1;
465 while (filp.f_pos < emd_dir->i_size){
466 struct umsdos_dirent entry;
467 if (umsdos_emd_dir_readentry(emd_dir,&filp,&entry)!=0){
468 ret = 0;
469 break;
470 }else if (entry.name_len != 0){
471 ret = 0;
472 break;
473 }
474 }
475 iput (emd_dir);
476 }
477 return ret;
478 }
479
480
481
482
483
484 int umsdos_findentry (
485 struct inode *dir,
486 struct umsdos_info *info,
487 int expect)
488
489
490 {
491 struct inode *emd_dir;
492 int ret = umsdos_find (dir,info,&emd_dir);
493 if (ret == 0){
494 if (expect != 0){
495 if (S_ISDIR(info->entry.mode)){
496 if (expect != 2) ret = -EISDIR;
497 }else if (expect == 2){
498 ret = -ENOTDIR;
499 }
500 }
501 }
502 iput (emd_dir);
503 return ret;
504 }
505