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