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