Subversion Repositories shark

Rev

Rev 24 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 1
/*
2
 * Project: HARTIK (HA-rd R-eal TI-me K-ernel)
3
 *
4
 * Coordinators: Giorgio Buttazzo <giorgio@sssup.it>
5
 *               Gerardo Lamastra <gerardo@sssup.it>
6
 *
7
 * Authors     : Massimiliano Giorgi <massy@hartik.sssup.it>
8
 * (see authors.txt for full list of hartik's authors)
9
 *
10
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
11
 *
12
 * http://www.sssup.it
13
 * http://retis.sssup.it
14
 * http://hartik.sssup.it
15
 */
16
 
17
/*
18
 * Copyright (C) 1999 Massimiliano Giorgi
19
 *
20
 * This program is free software; you can redistribute it and/or modify
21
 * it under the terms of the GNU General Public License as published by
22
 * the Free Software Foundation; either version 2 of the License, or
23
 * (at your option) any later version.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
 * GNU General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU General Public License
31
 * along with this program; if not, write to the Free Software
32
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
33
 *
34
 */
35
 
36
/*
24 pj 37
 * CVS :        $Id: msdos_i.c,v 1.2 2002-10-28 08:24:43 pj Exp $
2 pj 38
 *
39
 * File:        $File$
24 pj 40
 * Revision:    $Revision: 1.2 $
41
 * Last update: $Date: 2002-10-28 08:24:43 $
2 pj 42
 */
43
 
44
#include <fs/types.h>
45
#include <fs/const.h>
46
#include <fs/stat.h>
47
#include <fs/assert.h>
48
 
49
#include "dcache.h"
50
#include "fs.h"
51
#include "msdos.h"
52
#include "msdos/msdos.h"
53
 
54
#include "debug.h"
55
 
56
/*
57
 * local DEBUG
58
 */
59
 
60
#define DEBUG_ADDCLUSTER KERN_DEBUG
24 pj 61
#undef DEBUG_ADDCLUSTER
2 pj 62
 
63
#define DEBUG_ADDCLUSTER_EXTRA KERN_DEBUG
64
#undef DEBUG_ADDCLUSTER_EXTRA
65
 
66
/**/
67
 
68
#ifdef DEBUG_ADDCLUSTER
69
#define printd0(fmt,args...) \
70
        if (debug_info) printk(DEBUG_ADDCLUSTER fmt,##args)
71
#else
72
#define printd0(fmt,args...)
73
#endif
74
 
75
#if defined(DEBUG_ADDCLUSTER)&&defined(DEBUG_ADDCLUSTER_EXTRA)
76
#define printd1(fmt,args...) \
77
        if (debug_info) printk(DEBUG_ADDCLUSTER fmt,##args)
78
#else
79
#define printd1(fmt,args...)
80
#endif
81
 
82
/*
83
 *
84
 */
85
 
86
static char *chr2str(char*s, int n)
87
{
88
  static char str[13];
89
  _assert(n<13);
90
  memcpy(str,s,n);
91
  str[n]='\0';
92
  return str;
93
}
94
 
95
void msdos_dump_direntry(struct directoryentry *ptr)
96
{
97
  printk(KERN_DEBUG "status    : 0x%02x",(int)ptr->name[0]);
98
  printk(KERN_DEBUG "filename  : '%s'",chr2str(ptr->name,8));
99
  printk(KERN_DEBUG "ext       : '%s'",chr2str(ptr->ext,3));
100
  printk(KERN_DEBUG "attribute : 0x%02x",ptr->attribute);
101
  printk(KERN_DEBUG "cluster   : %04x",ptr->cluster);
102
  printk(KERN_DEBUG "size      : %li",(long)ptr->size);
103
  printk(KERN_DEBUG "time      : %li",(long)ptr->time);
104
}
105
 
106
/* what is the logical sector of a cluster into the fat */
107
static __inline __uint32_t __cluster2lsect(struct super_block *sb,
108
                                           __uint16_t cluster)
109
{
110
  return MSDOS_SB(sb).lfat+((__uint32_t)cluster*2)/SECTORSIZE;
111
}
112
 
113
/* what is the offset of a cluster into the fat */
114
static __inline __uint32_t __cluster2offs(__uint16_t cluster)
115
{
116
  return ((__uint32_t)cluster*2)%SECTORSIZE;
117
}
118
 
119
/**/
120
 
121
static __inline__ void __lock(struct super_block *sb,
122
                                dcache_t *buf[],
123
                                __uint32_t lsect)
124
{
125
  _assert(buf[0]==NULL);
126
  buf[0]=dcache_lock(sb->sb_dev,lsect);
127
}
128
 
129
static __inline__ void __unlock(struct super_block *sb,
130
                                dcache_t *buf[])
131
{
132
  _assert(buf[0]!=NULL);
133
  dcache_unlock(buf[0]);
134
  buf[0]=NULL;
135
}
136
 
137
static __inline__ void __acquire(struct super_block *sb,
138
                                dcache_t *buf[],
139
                                __uint32_t lsect)
140
{
141
  int i=0;
142
  _assert(buf[0]==NULL);
143
  _assert(MSDOS_SB(sb).nfat<=MAXFATS);
144
  for (i=0;i<MSDOS_SB(sb).nfat;i++) {
145
    buf[i]=dcache_acquire(sb->sb_dev,lsect);
146
    _assert(buf[i]!=NULL);
147
    lsect+=MSDOS_SB(sb).spf;
148
  }
149
}
150
 
151
static __inline__ void __release(struct super_block *sb,
152
                                dcache_t *buf[])
153
{
154
  int i;
155
  _assert(buf[0]!=NULL);
156
  for (i=MSDOS_SB(sb).nfat-1;i>=0;i--) {
157
    _assert(buf[i]!=NULL);
158
    dcache_release(buf[i]);
159
  }
160
  buf[0]=NULL;
161
}
162
 
163
static __inline__ __uint16_t __getcluster(struct super_block *sb,
164
                                          dcache_t *buf[],
165
                                          __uint16_t offs)
166
{
167
  _assert(buf[0]!=NULL);
168
  return *(__uint16_t*)(buf[0]->buffer+offs);  
169
}
170
 
171
static __inline__ void __setcluster(struct super_block *sb,
172
                                    dcache_t *buf[],
173
                                    __uint16_t offs,
174
                                    __uint16_t val)
175
{
176
  int i;
177
  _assert(buf[0]!=NULL);
178
  for (i=0;i<MSDOS_SB(sb).nfat;i++) {
179
    _assert(buf[i]!=NULL);
180
    *(__uint16_t*)(buf[i]->buffer+offs)=val;
181
    dcache_dirty(buf[i]);
182
    dcache_skipwt(buf[i]);
183
  }
184
}
185
 
186
/*
187
 *
188
 */
189
 
190
__uint16_t msdos_nextcluster(struct super_block *sb, __uint16_t cluster)
191
{
192
  dcache_t *buf[MAXFATS];
193
  __uint32_t lsect;
194
  __uint16_t  offs;
195
  __uint16_t  ret;
196
 
197
  buf[0]=NULL;
198
  lsect=__cluster2lsect(sb,cluster);
199
  offs=__cluster2offs(cluster);
200
 
201
  __lock(sb,buf,lsect);
202
  ret=__getcluster(sb,buf,offs);  
203
  __unlock(sb,buf);
204
 
205
  return ret;
206
}
207
 
208
void msdos_freecluster(struct super_block *sb, __uint16_t cluster)
209
{
210
  dcache_t   *buf[MAXFATS];
211
  __uint32_t lsect;
212
  __uint16_t offs;
213
 
214
  buf[0]=NULL;
215
  lsect=__cluster2lsect(sb,cluster);
216
  offs=__cluster2offs(cluster);
217
 
218
  __acquire(sb,buf,lsect);
219
 
220
  _assert(__getcluster(sb,buf,offs)!=FREECLUSTER);
221
  __setcluster(sb,buf,offs,FREECLUSTER);
222
 
223
  __release(sb,buf);
224
  return;
225
}
226
 
227
void msdos_lastcluster(struct super_block *sb, __uint16_t cluster)
228
{
229
  dcache_t   *buf[MAXFATS];
230
  __uint32_t lsect;
231
  __uint16_t offs;
232
 
233
  buf[0]=NULL;
234
  lsect=__cluster2lsect(sb,cluster);
235
  offs=__cluster2offs(cluster);
236
 
237
  __acquire(sb,buf,lsect);
238
 
239
  //_assert(__getcluster(sb,buf,offs)==FREECLUSTER);
240
  _assert(__getcluster(sb,buf,offs)!=LASTCLUSTER);
241
  __setcluster(sb,buf,offs,LASTCLUSTER);
242
 
243
  __release(sb,buf);
244
  return;
245
}
246
 
247
__uint16_t msdos_addcluster(struct super_block *sb, __uint16_t lacluster)
248
{
249
  dcache_t   *buf[MAXFATS];
250
  __uint32_t lsect;
251
  __uint16_t offs;
252
  __uint32_t olsect;
253
  __uint16_t cluster,stcluster;
254
 
255
  printd0("msdos_addcluster START");
256
 
257
  stcluster=cluster=MSDOS_SB(sb).stclust;  
258
  olsect=0;
259
  buf[0]=NULL;
260
 
261
  printd0("searching from cluster 0x%04lx",(long)stcluster);
262
 
263
  for (;;) {
264
    lsect=__cluster2lsect(sb,cluster);
265
    offs=__cluster2offs(cluster);
266
 
267
    if (lsect>=MSDOS_SB(sb).lroot) {
268
      cluster=STARTCLUSTER;
269
      lsect=__cluster2lsect(sb,cluster);
270
      offs=__cluster2offs(cluster);
271
      _assert(lsect<MSDOS_SB(sb).lroot);
272
    }
273
 
274
    if (lsect!=olsect) {
275
      if (buf[0]!=NULL) __release(sb,buf);
276
      __acquire(sb,buf,lsect);
277
      printd1("read sector %li",(long)lsect);
278
      olsect=lsect;
279
    }
280
 
281
    if (__getcluster(sb,buf,offs)==FREECLUSTER) {
282
      printd0("cluster 0x%04lx (into FAT lsect: %li) added to 0x%04lx",
283
              (long)cluster,(long)lsect,(long)lacluster);
284
      MSDOS_SB(sb).stclust=cluster;
285
      __setcluster(sb,buf,offs,LASTCLUSTER);
286
 
287
      /* if lacluster is not a cluster we do NOT change the FAT table!*/
288
      if (lacluster==NO_CLUSTER) break;
289
      __release(sb,buf);
290
 
291
      lsect=__cluster2lsect(sb,lacluster);
292
      offs=__cluster2offs(lacluster);
293
      __acquire(sb,buf,lsect);
294
      _assert(__getcluster(sb,buf,offs)==LASTCLUSTER);
295
      __setcluster(sb,buf,offs,cluster);
296
      break;
297
    }
298
 
299
    cluster++;
300
    if (cluster==stcluster) {
301
      cluster=NO_CLUSTER;
302
      break;
303
    }
304
  }  
305
 
306
  __release(sb,buf);
307
  printd0("msdos_addcluster END");
308
  return cluster;
309
}
310
 
311
void msdos_freeclusterchain(struct super_block *sb, __uint16_t cluster)
312
{
313
  dcache_t *buf[MAXFATS];
314
  __uint32_t  lsect;
315
  __uint16_t  offs;
316
  __uint32_t  olsect;
317
 
318
  buf[0]=NULL;
319
  olsect=0;
320
 
321
  for (;;) {
322
    lsect=__cluster2lsect(sb,cluster);
323
    offs=__cluster2offs(cluster);
324
 
325
    if (lsect!=olsect) {
326
      if (buf[0]!=NULL) __release(sb,buf);
327
      __acquire(sb,buf,lsect);
328
      olsect=lsect;
329
    }
330
 
331
    cluster=__getcluster(sb,buf,offs);
332
    _assert(cluster!=FREECLUSTER);
333
    __setcluster(sb,buf,offs,FREECLUSTER);
334
 
335
    if (cluster==LASTCLUSTER) break;
336
  }  
337
 
338
  __release(sb,buf);  
339
  return;
340
}
341
 
342
/*
343
 *
344
 */
345
 
346
/* from FS specific filename into 'de' to the general filename into 'str' */
347
int msdos_formatname(struct directoryentry *de, struct qstr *str)
348
{  
349
  char *s=str->name;
350
  char *ptr=de->name;
351
  int i;
352
 
353
  if (*ptr==0x05) *s++=0xed;
354
  else *s++=*ptr++;
355
  i=sizeof(de->name)-1;
356
  while (i-->0) {
357
    if (*ptr==' '||*ptr=='\0') break;
358
    *s++=*ptr++;
359
  }
360
 
361
  if (de->ext[0]!=' '&&de->ext[0]!='\0') {
362
    *s++='.';
363
    ptr=de->ext;
364
    i=sizeof(de->ext);
365
    while (i-->0) {
366
      if (*ptr==' '||*ptr=='\0') break;
367
      *s++=*ptr++;
368
    }
369
  }
370
 
371
  *s++='\0';
372
 
373
  str->nameptr=NULL;
374
  return 0;
375
}
376
 
377
/* all filename are traslated in upper case */
378
#define _up(x) (((x)>='a'&&(x)<='z')?(x)-'a'+'A':(x))
379
 
380
/* from the general filename into 'str' to FS specific filename into 'de' */
381
int msdos_deformatname(struct qstr *str,struct directoryentry *de)
382
{
383
  char *s=QSTRNAME(str);
384
  char *ptr=de->name;
385
  int i;
386
 
387
  memset(de->name,' ',sizeof(de->name));
388
  memset(de->ext,' ',sizeof(de->ext));
389
 
390
  i=0;
391
  for (i=0;i<sizeof(de->name);i++,s++,ptr++) {    
392
    if (*s=='.'||*s=='\0') break;
393
    *ptr=_up(*s);
394
  }
395
  if (*s=='\0') return 0;
396
 
397
  while (*s!='.') {
398
    if (*s=='\0') return 0;
399
    s++;
400
  }
401
 
402
  ptr=de->ext;
403
  s++;
404
  for (i=0;i<sizeof(de->name);i++,s++,ptr++) {    
405
    if (*s=='.'||*s=='\0') break;
406
    *ptr=_up(*s);
407
  }
408
 
409
 
410
  return 0;
411
}
412
 
413
static int msdos_dummy_truncate(struct inode *in, __off_t len)
414
{
415
  return -1;
416
}
417
 
418
static int msdos_truncate(struct inode *in, __off_t len)
419
{
420
  int numclusters;
421
  int cl,pcl;
422
 
423
  if (len>=in->i_st.st_size) return 0;
424
 
425
  if (len==0) {
426
    msdos_freeclusterchain(in->i_sb,MSDOS_I(in).scluster);
427
    MSDOS_I(in).scluster=FREE_CLUSTER;
428
    in->i_st.st_size=0;
429
    in->i_dirty=1;
430
    return 0;
431
  }
432
 
433
  numclusters=(len-1)/(MSDOS_SB(in->i_sb).spc*(long)SECTORSIZE)+1;
434
 
435
  /* walk on cluster chain */
436
  pcl=-1;
437
  cl=MSDOS_I(in).scluster;  
438
  while (numclusters-->0) {
439
    pcl=cl;
440
    cl=msdos_nextcluster(in->i_sb,cl);
441
  }
442
  if (cl!=LASTCLUSTER) {
443
    _assert(pcl!=-1);
444
    msdos_lastcluster(in->i_sb,pcl);
445
    msdos_freeclusterchain(in->i_sb,cl);
446
  }
447
 
448
  in->i_st.st_size=len;
449
  in->i_dirty=1;
450
  return 0;
451
}
452
 
453
/* msdos_create_inode() and msdos_lockup() are very similar */
454
/* they should be share code */
455
 
456
static struct inode *msdos_create_inode(struct inode *in, struct dentry *den)
457
{
458
  struct inode *in2;
459
  struct directoryentry *de;
460
  dcache_t *buf;
461
  __uint32_t lsect;
462
  __uint16_t  ldisk;
463
  __uint16_t cluster,prevcluster;
464
  int flagroot;
465
  int spc;
466
  int i,j;
467
  int res;
468
 
469
  /* for safety ;-) */
470
  if (!__S_ISDIR(in->i_st.st_mode)) return NULL;
471
 
472
  flagroot=(((in->i_st.st_ino&CLUSTER_MASK)>>CLUSTER_SHIFT)==ROOT_CLUSTER);
473
  if (flagroot) {
474
    cluster=SPECIAL_CLUSTER;
475
    lsect=MSDOS_SB(in->i_sb).lroot;
476
    spc=MSDOS_SB(in->i_sb).rootsect;
477
  } else {
478
    cluster=MSDOS_I(in).scluster;
479
    lsect=msdos_cluster2sector(in,cluster);
480
    _assert(lsect!=(__uint32_t)-1);
481
    spc=MSDOS_SB(in->i_sb).spc;
482
  }
483
 
484
  printk1("msdos create inode: start directory scanning");
485
 
486
  ldisk=in->i_sb->sb_dev;
487
  /* for every cluster... */
488
  for (;;) {
489
 
490
    /* for every sectors... */
491
    for (j=0;j<spc;j++,lsect++) {
492
      buf=dcache_acquire(ldisk,lsect);
493
 
494
      printk1("msdos create inode: logical sector %li",(long)lsect);
495
 
496
      if (buf==NULL) {
497
        printk1("msdos create inode: can't read sector");
498
        return NULL;
499
      }
500
 
501
      /* for every directory entry... */
502
      de=(struct directoryentry *)(buf->buffer);
503
      for (i=0;i<SECTORSIZE/DIRENTRYSIZE;i++) {
504
 
505
        if (msdos_isfreeentry(de+i)) {
506
          printk1("msdos create inode: found free entry");
507
 
508
          in2=catch_inode();
509
          printk1("-------------------");        
510
          if (in2==NULL) {
511
            printk1("msdos create inode: can't get free inode!");
512
            dcache_release(buf);
513
            return NULL;           
514
          }
515
 
516
          in2->i_sb=in->i_sb;
517
          in2->i_st.st_ino=CLUOFF2INODE(cluster,j*SECTORSIZE/DIRENTRYSIZE+i);
518
          res=in2->i_sb->sb_op->init_inode(in2);
519
          if (res!=0) {
520
            printk1("msdos create inode: can't init inode!");
521
            free_inode(in2);
522
            dcache_release(buf);
523
            return NULL;    
524
          }
525
 
526
          msdos_markentrybusy(de+i);
527
          msdos_deformatname(&den->d_name,de+i);
528
          dcache_dirty(buf);
529
 
530
          dcache_release(buf);
531
          return in2;
532
        }
533
 
534
      } /* end directory entry loop */
535
 
536
      dcache_release(buf);
537
 
538
      printk1("msdos create inode: next sector");
539
 
540
    } /* end sector loop */
541
 
542
    if (flagroot) {
543
      printk1("msdos create inode : no free slot (can't add one)");
544
      return NULL;
545
    }
546
 
547
    cluster=msdos_nextcluster(in->i_sb,prevcluster=cluster);
548
    if (cluster==LASTCLUSTER) {
549
      printk1("msdos create inode: no free slot (try to add one)");
550
 
551
      cluster=msdos_addcluster(in->i_sb,prevcluster);
552
      if (cluster==NO_CLUSTER) {
553
        printk1("msdos create inode: can't add cluster");
554
        return NULL;
555
      }
556
 
557
      /* zeroing the new cluster */
558
      lsect=msdos_cluster2sector(in,cluster);
559
      _assert(lsect!=(__uint32_t)-1);
560
      for (j=0;j<spc;j++,lsect++) {
561
        buf=dcache_acquire(ldisk,lsect);
562
        _assert(buf!=NULL);
563
        memset(buf->buffer,0,SECTORSIZE);
564
        dcache_dirty(buf);
565
        dcache_release(buf);
566
      }
567
 
568
      printk1("msdos create inode: added cluster");
569
 
570
    }
571
    lsect=msdos_cluster2sector(in,cluster);
572
    _assert(lsect!=(__uint32_t)-1);
573
 
574
    printk1("msdos create inode: next cluster");
575
 
576
  } /* end cluster loop */
577
 
578
}
579
 
580
static struct inode *msdos_lookup(struct inode *in, struct dentry *den)
581
{
582
  struct inode *in2;
583
  struct directoryentry *de;
584
  struct qstr str;
585
  dcache_t *buf;
586
  __uint32_t lsect;
587
  __uint16_t  ldisk;
588
  __uint16_t cluster;
589
  int flagroot;
590
  int spc;
591
  int i,j;
592
  int res;
593
 
594
  printk1("msdos lookup: START for %s",QSTRNAME(&(den->d_name)));
595
 
596
  /* for safety ;-) */
597
  if (!__S_ISDIR(in->i_st.st_mode)) return NULL;
598
 
599
  printk1("msdos lookup: is directory... ok");
600
 
601
  flagroot=(((in->i_st.st_ino&CLUSTER_MASK)>>CLUSTER_SHIFT)==ROOT_CLUSTER);
602
  if (flagroot) {
603
    cluster=SPECIAL_CLUSTER;
604
    lsect=MSDOS_SB(in->i_sb).lroot;
605
    spc=MSDOS_SB(in->i_sb).rootsect;
606
  } else {
607
    cluster=MSDOS_I(in).scluster;
608
    lsect=msdos_cluster2sector(in,cluster);
609
    _assert(lsect!=(__uint32_t)-1);
610
    spc=MSDOS_SB(in->i_sb).spc;
611
  }
612
 
613
  printk1("msdos lookup: start directory scanning");
614
 
615
  ldisk=in->i_sb->sb_dev;
616
  /* for every cluster... */
617
  for (;;) {
618
 
619
    /* for every sectors... */
620
    for (j=0;j<spc;j++,lsect++) {
621
      buf=dcache_lock(ldisk,lsect);
622
 
623
      printk1("msdos lookup: logical sector %li",(long)lsect);
624
 
625
      if (buf==NULL) {
626
        printk1("msdos lookup: can't read sector");
627
        return NULL;
628
      }
629
 
630
      /* for every directory entry... */
631
      de=(struct directoryentry *)(buf->buffer);
632
      for (i=0;i<SECTORSIZE/DIRENTRYSIZE;i++) {
633
        if (msdos_islastentry(de+i)) {
634
          /* last entry... not found! */
635
          dcache_unlock(buf);
636
          printk1("msdos lookup: NOT found");
637
          return NULL;
638
        }
639
 
640
        /* if it' an invalid entry (not a regular file or directory entry) */
641
        if (msdos_isunvalidentry(de+i)) continue;
642
 
643
        /* extract name */
644
        res=msdos_formatname(de+i,&str);
645
        if (res!=0) {
646
          dcache_unlock(buf);
647
          printk1("msdos lookup: can't extract filename");
648
          return NULL;
649
        }
650
 
651
        printk1e("msdos lookup: filename '%s'",QSTRNAME(&str));
652
 
653
        /* compare name and if found... */
654
        if (den->d_op->d_compare(den,&den->d_name,&str)==0) {
655
 
656
          printk1("msdos lookup: found");        
657
          in2=catch_inode();
658
          printk1("-------------------");
659
 
660
          if (in2==NULL) {
661
            printk1("msdos lookup: can't get free inode!");
662
            dcache_unlock(buf);
663
            return NULL;    
664
          }
665
          in2->i_sb=in->i_sb;
666
          in2->i_st.st_ino=CLUOFF2INODE(cluster,j*SECTORSIZE/DIRENTRYSIZE+i);
667
          res=in2->i_sb->sb_op->read_inode(in2);
668
          if (res!=0) {
669
            printk1("msdos lookup: can't read inode!");
670
            free_inode(in2);
671
            dcache_unlock(buf);
672
            return NULL;    
673
          }
674
 
675
          dcache_unlock(buf);
676
          return in2;
677
        }
678
 
679
      } /* end directory entry loop */
680
 
681
      dcache_unlock(buf);
682
      printk1("msdos lookup: next sector");
683
 
684
    } /* end sector loop */
685
 
686
    if (flagroot) {
687
      printk1("msdos lookup: NOT found (no other entry into root dir)");
688
      return NULL;
689
    }
690
 
691
    cluster=msdos_nextcluster(in->i_sb,cluster);
692
    if (cluster==0||cluster>=0xfff0) {
693
      printk1("msdos lookup: NOT found (end cluster)");  
694
      return NULL;
695
    }
696
    lsect=msdos_cluster2sector(in,cluster);
697
    _assert(lsect!=(__uint32_t)-1);
698
 
699
    printk1("msdos lookup: next cluster");
700
 
701
  } /* end cluster loop */
702
 
703
}
704
 
705
static int msdos_dummy_unlink(struct dentry *d)
706
{
707
  return EROFS;
708
}
709
 
710
static int msdos_unlink(struct dentry *d)
711
{
712
  printkd("msdos_unlink: START");
713
 
714
  /* only one dentry can own this inode... */
715
  _assert(d->d_inode->i_dlink==1);
716
 
717
  /* nothing to do */
718
 
719
  /* update link count */
720
  d->d_inode->i_st.st_nlink--;
721
  _assert(d->d_inode->i_st.st_nlink==0);
722
 
723
  printkd("msdos_unlink: END");
724
  return 0;  
725
}
726
 
727
static void msdos_destroy(struct inode *in)
728
{
729
  msdos_truncate(in,0);
730
  return;
731
}
732
 
733
/* ----------------- */
734
 
735
struct inode_operations msdos_inode_ro_operations={
736
  &msdos_file_ro_operations,
737
  msdos_create_inode,
738
  msdos_lookup,
739
  msdos_dummy_unlink,
740
  msdos_destroy,
741
  msdos_dummy_truncate
742
};
743
 
744
struct inode_operations msdos_inode_rw_operations={
745
  &msdos_file_rw_operations,
746
  msdos_create_inode,
747
  msdos_lookup,
748
  msdos_unlink,
749
  msdos_destroy,
750
  msdos_truncate
751
};
752
 
753
 
754
/*
755
 *
756
 * for inlines
757
 *
758
 */
759
 
760
int msdos_islastentry(struct directoryentry *de)
761
{
762
  return (*((de)->name)==LASTENTRYCHAR);
763
}
764
 
765
int msdos_isunvalidentry(struct directoryentry *de)
766
{
767
  return (*((de)->name)==ERASEDENTRYCHAR)||
768
    ((de)->attribute&ATTR_VOLUME)||
769
    (msdos_islastentry(de));
770
}