source: buchla-68k/libcio/filesys.c

Last change on this file was f261cc8, checked in by Thomas Lopatic <thomas@…>, 3 years ago

Minor cleanup.

  • Property mode set to 100644
File size: 22.5 KB
Line 
1/*
2   =============================================================================
3        filesys.c -- file system support functions
4        Version 44 -- 1987-11-15 -- D.N. Lynx Crowe
5
6        These functions support a {MS,GEM}DOS|TOS-like file system.
7        Only 12 bit FAT entries are supported.
8        Subdirectories are not supported in this version.
9   =============================================================================
10*/
11
12#define DEBUGIT         0
13
14#include "ram.h"
15
16#define FAT_EOF         0x0FF8
17
18#define IO_ERR          -1
19#define IO_OK           0
20#define IO_EOF          1
21
22#define DE_NULL         ((struct dirent *)0L)
23
24#if DEBUGIT
25short   fsdebug;
26#endif
27
28struct  bpb     *_thebpb;               /* BIOS parameter block pointer */
29struct  dirent  _thedir[MAXDIRNT];      /* directory */
30struct  dirent  *_dptr;                 /* internal directory pointer */
31
32uint8_t _thefat[MAXFAT * BPSEC];        /* file allocation table */
33
34int16_t _fatin;                         /* FAT has been read */
35int16_t _dirin;                         /* directory has been read */
36int16_t _bpbin;                         /* BPB has been read */
37int16_t _fatmod;                        /* FAT modified flag */
38int16_t _dirmod;                        /* directory modified flag */
39
40int32_t _berrno;                        /* BIOS error number */
41
42/*
43   =============================================================================
44        _cl2lsn(bpp, clnum) -- return logical sector number for cluster 'clnum'
45        using BPB pointed to by 'bpp'
46   =============================================================================
47*/
48
49int16_t _cl2lsn(struct bpb *bpp, int16_t clnum)
50{
51        return(bpp->datrec + (bpp->clsiz * (clnum - 2)) );
52}
53
54/*
55   =============================================================================
56        _gtcl12(fat, cl) -- return 12 bit cluster entry 'cl' from FAT pointed
57        to by 'fat'
58   =============================================================================
59*/
60
61int16_t _gtcl12(uint8_t *fat, int16_t cl)
62{
63        int16_t cla;
64        uint16_t clt;
65
66        cla = cl + (cl >> 1);
67        clt = (0xFF00u & ((uint16_t)fat[cla + 1] << 8))
68                | (0x00FFu & fat[cla]);
69
70        if (cl & 1)
71                clt >>= 4;
72
73        clt &= 0x0FFFu;
74        return((int16_t)clt);
75}
76
77/*
78   =============================================================================
79        _getfat(bufad, bpp, nfat) -- get FAT 'nfat' into buffer
80        pointed to by 'bufad' using BPB pointed to by 'bpp'
81   =============================================================================
82*/
83
84int16_t _getfat(uint8_t *bufad, struct bpb *bpp, int16_t nfat)
85{
86        int16_t fatsec;
87
88        fatsec = nfat ? bpp->fatrec : (bpp->fatrec - bpp->fsiz);
89        return((int16_t)BIOS(B_RDWR, 0, bufad, bpp->fsiz, fatsec, 0));
90}
91
92/*
93   =============================================================================
94        _rdfat(bufad, bpp) -- read FAT into buffer pointed to by 'bufad'
95        using BPB pointed to by 'bpp'
96   =============================================================================
97*/
98
99int16_t _rdfat(uint8_t *bufad, struct bpb *bpp)
100{
101        if (_getfat(bufad, bpp, 0)) {
102
103                if (_getfat(bufad, bpp, 1))
104                        return(IO_ERR);         /* couldn't read either FAT */
105                else
106                        return(1);              /* secondary FAT read OK */
107
108        } else
109                return(0);                      /* main FAT read OK */
110}
111
112/*
113   =============================================================================
114        _rdroot(buf, bpp) -- read root directory into buffer
115        pointed to by 'buf' using BPB pointed to by 'bpp'
116   =============================================================================
117*/
118
119int16_t _rdroot(struct dirent *buf, struct bpb *bpp)
120{
121        return((int16_t)BIOS(B_RDWR, 0, buf, bpp->rdlen,
122                (bpp->fatrec + bpp->fsiz), 0));
123}
124
125/*
126   =============================================================================
127        _nsic(fcp, bpp, fp) -- get the next sector in the file controlled
128        by the FCB at 'fcp', using the BPB pointed to by 'bpp' and
129        the FAT pointed to by 'fp'.  Returns 0 if successful, or -1 on error,
130        or 1 on EOF;
131   =============================================================================
132*/
133
134int16_t _nsic(struct fcb *fcp, struct bpb *bpp, uint8_t *fp)
135{
136        register int16_t tfe;
137
138        /* check the FCB flags */
139
140        if (!(fcp->modefl & FC_OPN)) {
141
142                errno = EINVAL;         /* not open */
143                return(IO_ERR);
144        }
145
146        if (fcp->modefl & FC_BAD) {
147
148                errno = EIO;            /* previous I/O error */
149                return(IO_ERR);
150        }
151
152        if (fcp->de.bclust EQ 0) {      /* no sectors allocated  (empty file) */
153
154                fcp->modefl |= FC_EOF;
155                return(IO_EOF);
156        }
157
158        /* update clsec and curlsn and see if we need a new cluster */
159
160        ++fcp->curlsn;
161
162        if (++fcp->clsec GE bpp->clsiz) {
163
164                /* new cluster needed -- follow the chain */
165
166                fcp->clsec = 0;
167                tfe = _gtcl12(fp, fcp->curcls);
168
169                if (tfe < 0x0FF0) {     /* see if we've got a good cluster */
170
171
172                        fcp->curcls = tfe;      /* good cluster, update fcb */
173                        fcp->curdsn = _cl2lsn(bpp, tfe);
174
175#if DEBUGIT
176        if (fsdebug)
177                printf("_nsic():  NXT curlsn=%ld, curcls=%u, curdsn=%ld\n",
178                        fcp->curlsn, fcp->curcls, fcp->curdsn);
179#endif
180
181                        return(IO_OK);
182                }
183
184                if (tfe < 0x0FF8) {     /* see if it's a bad cluster */
185
186                        fcp-> modefl |= (FC_BAD | FC_EOF);      /* bad one */
187
188#if DEBUGIT
189        if (fsdebug)
190                printf("_nsic():  IO_ERR - curlsn=%ld, curcls=%u, curdsn=%ld\n",
191                        fcp->curlsn, fcp->curcls, fcp->curdsn);
192#endif
193
194                        return(IO_ERR);
195                }
196
197                fcp->modefl |= FC_EOF;  /* EOF hit -- set EOF in FCB */
198                return(IO_EOF);
199
200        } else {
201
202                ++fcp->curdsn;  /* advance to next sector in current cluster */
203
204#if DEBUGIT
205        if (fsdebug)
206                printf("_nsic():  CUR curlsn=%ld, curcls=%u, curdsn=%ld\n",
207                        fcp->curlsn, fcp->curcls, fcp->curdsn);
208#endif
209
210                return(IO_OK);
211        }
212}
213
214/*
215   =============================================================================
216        _dsrch(de) -- search for the directory entry pointed to by 'de'
217        in the current directory
218   =============================================================================
219*/
220
221struct dirent *_dsrch(struct dirent *de)
222{
223        int16_t i, dl;
224        register struct dirent *dp;
225
226        dp = _thedir;
227        dl = _thebpb->rdlen * (_thebpb->recsiz / (int16_t)DENTSIZE);
228
229        for (i = 0; i < dl; i++) {              /* check each entry */
230
231                /* see if we've found it */
232
233                if (0 EQ memcmpu(de->fname, dp->fname, 11))
234                        return(dp);
235
236                /* check for end of used entries */
237
238                if ('\0' EQ dp->fname[0])
239                        return(DE_NULL);
240
241                dp++;   /* point at next entry to check */
242        }
243
244        return(DE_NULL);
245}
246
247/*
248   =============================================================================
249        _dsnew() -- search for an available directory entry in the current
250        directory.
251   =============================================================================
252*/
253
254struct dirent *_dsnew(void)
255{
256        int16_t i, dl;
257        register struct dirent *dp;
258
259        dp = _thedir;
260        dl = _thebpb->rdlen * (_thebpb->recsiz / (int16_t)DENTSIZE);
261
262        for (i = 0; i < dl; i++) {              /* check each entry */
263
264                /* check for a deleted entry */
265
266                if (0x00E5 EQ (0x00FF & dp->fname[0]))
267                        return(dp);
268
269                /* check for end of used entries */
270
271                if ('\0' EQ dp->fname[0])
272                        return(dp);
273
274                dp++;   /* point at next entry to check */
275        }
276
277        return(DE_NULL);        /* couldn't find an available entry */
278}
279
280/*
281   =============================================================================
282        _deadio(fcp, err) -- mark the FCB pointed to by 'fcp' as 'in error'
283   =============================================================================
284*/
285
286void _deadio(struct fcb *fcp, int16_t err)
287{
288        fcp->clsec = 0;
289        fcp->curcls = 0;
290        fcp->curlsn = 0L;
291        fcp->curdsn = 0L;
292        fcp->curlen = 0L;
293        fcp->modefl &= ~FC_OPN;
294        fcp->modefl |= FC_ERR;
295        errno = err;
296}
297
298/*
299   =============================================================================
300        _seek(fcp) -- seek to logical sector number in FCB pointed to by 'fcp'.
301        Returns:  -1 = error; 0 = not at EOF; 1 = soft EOF; 2 = hard EOF.
302   =============================================================================
303*/
304
305int16_t _seek(struct fcb *fcp)
306{
307        register int16_t acls, rcls, nc;
308        int16_t sic, spc;
309
310        if (!(fcp->modefl & FC_OPN)) {          /* file must be open */
311
312                errno = EINVAL;                 /* invalid request */
313                return(-1);                     /* return with an error */
314        }
315
316        if (fcp->curlsn GT fcp->asects) {       /* error if seek past EOF */
317
318#if     DEBUGIT
319        if (fsdebug)
320                printf("_seek():  ERROR - seek past EOF - curlsn=%ld, asects=%ld\n",
321                        fcp->curlsn, fcp->asects);
322#endif
323
324                errno = EINVAL;                 /* invalid request */
325                return(-1);                     /* return with an error */
326        }
327               
328        spc = _thebpb->clsiz;                   /* get sectors per cluster */
329        rcls = fcp->curlsn / spc;               /* calculate relative cluster */
330        sic = fcp->curlsn - (rcls * spc);       /* calculate sector in cluster */
331        acls = (int16_t)micon16(fcp->de.bclust);        /* get first cluster */
332        fcp->modefl &= ~FC_EOF;                 /* turn off the EOF flag */
333
334#if DEBUGIT
335        if (fsdebug) {
336                printf("_seek():  ENTRY curlsn=%ld, acls=%u, sic=%d, curdsn=%ld, rcls=%u, asects=%ld\n",
337                        fcp->curlsn, acls, sic, fcp->curdsn, rcls, fcp->asects);
338        }
339#endif
340
341        if (fcp->curlsn EQ fcp->asects) {       /* see if we seeked to EOF */
342
343                fcp->modefl |= FC_EOF;          /* flag the EOF condition */
344
345#if DEBUGIT
346        if (fsdebug)
347                printf("_seek():  EOF curlsn=%ld, acls=%u, sic=%d, curdsn=%ld\n",
348                        fcp->curlsn, acls, sic, fcp->curdsn);
349#endif
350
351                if (acls EQ 0)                  /* see if anything allocated */
352                        return(2);              /* hard EOF if nothing there */
353
354                if (sic EQ 0)                   /* see if first in cluster */
355                        return(2);              /* hard EOF if so */
356        }
357
358
359        for (nc = 0; nc < rcls; nc++) {         /* follow the FAT chain */
360
361                acls = _gtcl12(_thefat, acls);  /* next cluster pointer */
362
363                if (acls LT 0x0FF0)             /* OK if it's a good cluster */
364                        continue;
365
366                fcp->modefl |= FC_ERR;          /* EOF or bad cluster hit */
367                errno = EINVAL;                 /* mark it as an invalid seek */
368
369                if (acls LT 0x0FF8) {           /* bad cluster ? */
370
371                        errno = EIO;            /* mark it as an I/O error */
372                        fcp->modefl |= FC_BAD;  /* mark FCB:  bad cluster hit */
373                }
374
375                return(IO_ERR);                 /* ERROR:  seek error */
376        }
377
378        fcp->curcls = acls;                     /* current cluster */
379        fcp->clsec = sic;                       /* sector in cluster */
380
381        fcp->curdsn = _cl2lsn(_thebpb, acls) + sic;     /* disk sector number */
382
383#if DEBUGIT
384        if (fsdebug)
385                printf("_seek():  OK curlsn=%ld, acls=%u, sic=%d, curdsn=%ld\n",
386                        fcp->curlsn, acls, sic, fcp->curdsn);
387#endif
388
389        if (fcp->curlsn EQ fcp->asects)         /* see if we're at EOF */
390                return(1);                      /* soft EOF */
391               
392        return(0);                              /* not EOF */
393}
394
395/*
396   =============================================================================
397        _ftrnc(dp) -- truncate file pointed to by directory entry 'dp'
398   =============================================================================
399*/
400
401int16_t _ftrnc(struct dirent *dp)
402{
403        register int16_t acls, ncls;
404
405#if     DEBUGIT
406        register int lim;
407
408        lim = _thebpb->numcl;
409#endif
410
411        acls = (int16_t)micon16(dp->bclust);    /* get first cluster number */
412
413        /* zap entries until EOF or bad cluster */
414
415#if     DEBUGIT
416        while (lim-- AND (acls LT 0x0FF0)) {
417#else
418        while (acls LT 0x0FF0) {
419#endif
420
421                ncls = _gtcl12(_thefat, acls);  /* get next cluster number */
422                _ptcl12(_thefat, acls, 0);      /* zap the current one */
423
424#if     DEBUGIT
425        if (fsdebug)
426                printf("_ftrnc():  zapped %d\n", acls);
427#endif
428
429                acls = ncls;                    /* point at the next one */
430        }
431
432        dp->flen = 0L;                          /* file length = 0 */
433        dp->bclust = 0;                         /* no sectors allocated */
434        _fatmod = TRUE;                         /* FAT got changed */
435        _dirmod = TRUE;                         /* directory got changed */
436
437#if     DEBUGIT
438        if (lim LE 0) {
439
440                errno = EIO;
441                printf("_ftrnc():  ERROR - lim went to %d\n", lim);
442                mdump(_thefat, (char *)_thefat+255, _thefat);
443                xtrap15();
444                return(FAILURE);
445        }
446#endif
447
448        return(SUCCESS);
449}
450
451/*
452   =============================================================================
453        _newcls() -- allocate a new cluster
454   =============================================================================
455*/
456
457int16_t _newcls(void)
458{
459        register int16_t tc, i;
460
461        tc = _thebpb->numcl;
462
463        for (i = 2; i < tc; i++)
464                if (0 EQ _gtcl12(_thefat, i))
465                        return(i);
466
467        return(0);      /* ERROR:  no empty clusters left */
468}
469
470/*
471   =============================================================================
472        _alcnew() -- allocate a new cluster to extend a file
473   =============================================================================
474*/
475
476int16_t _alcnew(struct fcb *fcp)
477{
478        register int16_t ac, nc, pc;
479
480#if     DEBUGIT
481        register int lim;
482#endif
483
484        if ((nc = _newcls())) {                 /* get a new cluster */
485
486#if     DEBUGIT
487                lim = (fcp->asects / _thebpb->clsiz) + 1;  /* limit search */
488#endif
489
490                _ptcl12(_thefat, nc, FAT_EOF);  /* mark new cluster as EOF */
491                pc = (int16_t)micon16(fcp->de.bclust);  /* get first cluster */
492
493#if     DEBUGIT
494        if (pc EQ 0) {
495
496                printf("_alcnew():  ERROR - pc EQ 0, bclust=$%04.4X, nc=%d\n",
497                        fcp->de.bclust, nc);
498                xtrap15();
499        }
500#endif
501
502                /* find end of allocation chain */
503
504#if     DEBUGIT
505                while (lim-- AND ((ac = _gtcl12(_thefat, pc)) < 0x0FF0)) {
506#else
507                while ((ac = _gtcl12(_thefat, pc)) < 0x0FF0) {
508#endif
509
510                        pc = ac;
511                }
512
513#if     DEBUGIT
514                if (lim LE 0) {
515
516                        printf("_alcnew():  ERROR - lim ran out, nc=%d\n", nc);
517                        mdump(_thefat, (char *)_thefat+63, _thefat);
518                        xtrap15();
519                        return(FAILURE);
520                }
521#endif
522
523                _ptcl12(_thefat, pc, nc);       /* add cluster to chain */
524                fcp->asects += _thebpb->clsiz;  /* update allocated sector count */
525                fcp->curcls = nc;               /* current cluster = new cluster */
526                fcp->clsec = 0;                 /* current sector in cluster = 0 */
527
528                fcp->curdsn = _cl2lsn(_thebpb, nc);     /* current disk sector */
529
530#if DEBUGIT
531                if (fsdebug) {
532
533                        printf("alcnew():  allocated cluster %d (%04.4x), ",
534                                nc, nc);
535                        printf("previous = %d (%04.04x), asects =%ld\n",
536                                pc, pc, fcp->asects);
537                }
538#endif
539
540                return(SUCCESS);                /* return:  file extended */
541
542        } else {
543
544#if DEBUGIT
545        if (fsdebug)
546                printf("_alcnew():  _newcls() FAILED\n");
547#endif
548
549                return(FAILURE);                /* return:  no clusters left */
550        }
551}
552
553/*
554   =============================================================================
555        _fmake(fcp) -- make a new file from the FCB pointed to by 'fcp'
556   =============================================================================
557*/
558
559int16_t _fmake(struct fcb *fcp)
560{
561        register struct dirent *dp;
562
563        if (DE_NULL EQ (dp = _dsnew()))         /* find a dirent */
564                return(FAILURE);
565
566        _dptr = dp;                             /* set the directory pointer */
567        memset(dp, 0, DENTSIZE);                /* clear the dirent */
568        memcpy(dp->fname, fcp->de.fname, 12);   /* setup file name, attribute */
569        dp->atrib |= F_ARCHIV;                  /* set the archive bit */
570        _dirmod = TRUE;                         /* directory got changed */
571        return(SUCCESS);
572}
573
574/*
575   =============================================================================
576        _opnvol() -- open a volume
577   =============================================================================
578*/
579
580int16_t _opnvol(void)
581{
582        register int32_t drc;
583
584        /* check for media change if we already have a BPB */
585
586        if (_bpbin) {
587
588                drc = BIOS(B_MCHG, 0);
589
590#if DEBUGIT
591        if (fsdebug) {
592
593                printf("_opnvol():  found _bpbin FALSE\n");
594                printf("_opnvol():  disk change test returned %ld\n", drc);
595        }
596#endif
597
598                if (drc)
599                        _bpbin = FALSE;
600        } else {
601
602#if DEBUGIT
603        if (fsdebug)
604                printf("_opnvol():  found _bpbin FALSE\n");
605#endif
606
607        }
608
609        if (!_bpbin) {          /* access the BPB */
610
611                _fatin = FALSE;         /* invalidate the FAT and directory */
612                _dirin = FALSE;
613
614                if (NULL EQ (_thebpb = (struct bpb *)BIOS(B_GBPB, 0))) {
615
616                        errno = EIO;    /* couldn't read the BPB */
617                        return(FAILURE);
618                }
619
620                _bpbin  = TRUE;
621        }
622
623        if (!_fatin) {          /* access the FAT */
624
625                _dirin = FALSE;
626
627                if (_rdfat(_thefat, _thebpb) < 0) {
628
629                        errno = EIO;    /* couldn't read either FAT */
630                        return(FAILURE);
631                }
632
633                _fatin  = TRUE;
634                _fatmod = FALSE;
635        }
636
637        if (!_dirin) {          /* access the root directory */
638
639                if (_rdroot(_thedir, _thebpb)) {
640
641                        errno = EIO;    /* couldn't read the directory */
642                        return(FAILURE);
643                }
644
645                _dirin  = TRUE;
646                _dirmod = FALSE;
647        }
648
649        return(SUCCESS);
650}
651
652/*
653   =============================================================================
654        _opfcb(fcp) -- open the FCB pointed to by 'fcp'.  Returns 0 if
655        opened successfully, -1 if an error occurred, with the error code
656        in errno.
657   =============================================================================
658*/
659
660int16_t _opfcb(struct fcb *fcp)
661{
662        int16_t rc;
663
664        /* check for an already open FCB */
665
666        if (fcp->modefl & FC_OPN) {
667
668                errno = EINVAL;
669                return(IO_ERR);
670        }
671
672        if (_opnvol()) {        /* open the volume */
673
674                _deadio(fcp, errno);
675                return(IO_ERR);
676        }
677
678        /* search the directory for the file */
679
680        if (DE_NULL EQ (_dptr = _dsrch(&fcp->de))) {
681
682                /* file doesn't exist -- see if we should create it */
683
684                if (!(fcp->modefl & FC_CR)) {
685               
686                        _deadio(fcp, ENOENT);   /* file nonexistant, not creating one */
687                        return(IO_ERR);
688                }
689
690                /* create the file */
691
692                if ((rc = _fmake(fcp))) {
693
694                        _deadio(fcp, EIO);      /* couldn't create the file */
695                        return(IO_ERR);
696                }
697
698        } else {
699
700                /* file exists -- check for writes to a read-only file */
701
702                if ( (fcp->de.atrib & F_RDONLY) AND
703                     (fcp->modefl & (FC_AP | FC_WR | FC_TR)) ) {
704
705                                /* can't append, write or truncate RO files */
706
707                                _deadio(fcp, EACCES);
708                                return(IO_ERR);
709                        }
710
711                /* check for append and not write */
712
713                if ((fcp->modefl & FC_AP) AND !(fcp->modefl & FC_WR)) {
714
715                        /* can't append if not open to write */
716
717                        _deadio(fcp, EACCES);
718                        return(IO_ERR);
719                }
720
721                /* check for create and exclusive with extant file */
722
723                if ((fcp->modefl & FC_CR) AND (fcp->modefl & FC_EX)) {
724
725                        /* file exists and open was create-exclusive */
726
727                        _deadio(fcp, EEXIST);
728                        return(IO_ERR);
729                }
730
731                /* truncate the file if requested */
732
733                if (fcp->modefl & FC_TR) {
734
735                        /* see if we can write */
736
737                        if (fcp->modefl & FC_WR) {
738
739                                /* truncate the file */
740
741                                if (_ftrnc(_dptr)) {
742
743                                        _deadio(fcp, EIO);      /* truncation failed */
744                                        return(IO_ERR);
745                                }
746
747                        } else {
748
749                                /* we can't write, so we can't truncate */
750
751                                _deadio(fcp, EACCES);
752                                return(IO_ERR);
753                        }
754                }
755        }
756
757        /* setup the FCB fields */
758
759        memcpy(&fcp->de, _dptr, DENTSIZE);
760        fcp->clsec = 0;
761        fcp->curcls = (int16_t)micon16(fcp->de.bclust);
762        fcp->offset = 0;
763        fcp->curlsn = 0L;
764        fcp->curdsn = fcp->de.bclust ? _cl2lsn(_thebpb, fcp->curcls) : 0;
765        fcp->curlen = (int32_t)micon32(fcp->de.flen);
766
767        fcp->asects = ((int16_t)(fcp->curlen / _thebpb->clsizb)
768                + ((fcp->curlen & (_thebpb->clsizb - 1)) ? 1 : 0))
769                * _thebpb->clsiz;
770
771        fcp->modefl &= ~(FC_EOF | FC_BAD | FC_ERR);
772        fcp->modefl |= FC_OPN;
773
774#if DEBUGIT
775        if (fsdebug)
776                SnapFCB(fcp);
777#endif
778
779        return(IO_OK);
780}
781
782/*
783   =============================================================================
784        _inifcb(fcp, name, ext, mode) -- initialize FCB pointed to by 'fcp'
785        for file named 'name'.'ext'.
786        Returns SUCCESS (0) if ok, FAILURE (-1) if not.
787   =============================================================================
788*/
789
790int16_t _inifcb(struct fcb *fcp, int8_t *name, int8_t *ext, uint16_t flags)
791{
792        int16_t fl;
793        register int16_t        i;
794        register int8_t *s1, *s2, c;
795
796        /* clear the FCB */
797
798        memset((int8_t *)fcp, 0, sizeof (struct fcb));
799
800        /* check for valid flags */
801
802        if (flags & ~(O_WRONLY|O_RDWR|O_NDELAY|O_APPEND|O_CREAT|O_TRUNC|O_EXCL|O_RAW))
803                return(FAILURE);
804
805
806        /* check the file name for length */
807
808        fl = TRUE;
809        s1 = name;
810
811        for (i = 0; i < 9; i++)
812                if (*s1++ EQ '\0') {
813
814                        fl = FALSE;
815                        break;
816                }
817
818        if (fl)
819                return(FAILURE);
820
821        /* check the file name extension for length */
822
823        fl = TRUE;
824        s1 = ext;
825
826        for (i = 0; i <4; i++)
827                if (*s1++ EQ '\0') {
828
829                        fl = FALSE;
830                        break;
831                }
832
833        if (fl)
834                return(FAILURE);
835
836
837        /* clear the file name and extension in the FCB to blanks */
838
839        memset(fcp->de.fname, ' ', 11);
840
841        /* move the file name into the FCB */
842
843        s1 = fcp->de.fname;
844        s2 = name;
845
846        for (i = 0; i < 8; i++) {
847
848                c = *s2++;
849
850                if ((c EQ '\0') OR (c EQ ' '))
851                        break;
852
853                *s1++ = c;
854        }
855
856        /* move the file name extension into the FCB */
857
858        s1 = fcp->de.fext;
859        s2 = ext;
860
861        for (i = 0; i < 3; i++) {
862
863                c = *s2++;
864
865                if ((c EQ '\0') OR (c EQ ' '))
866                        break;
867
868                *s1++ = c;
869        }
870
871        /* set the flags in the FCB and exit */
872
873        if (flags & O_RDONLY)
874                fcp->modefl |= FC_RD;
875
876        if (flags & O_WRONLY)
877                fcp->modefl |= FC_WR;
878
879        if (flags & O_RDWR)
880                fcp->modefl |= FC_RW;
881
882        if (flags & O_NDELAY)
883                fcp->modefl |= FC_NB;
884
885        if (flags & O_APPEND)
886                fcp->modefl |= FC_AP;
887
888        if (flags & O_CREAT)
889                fcp->modefl |= FC_CR;
890
891        if (flags & O_TRUNC)
892                fcp->modefl |= FC_TR;
893
894        if (flags & O_EXCL)
895                fcp->modefl |= FC_EX;
896
897        if (flags & O_RAW)
898                fcp->modefl |= FC_BF;
899
900        return(SUCCESS);
901}
902
903/*
904   =============================================================================
905        ClsFile() -- Closes the file controlled by the FCB pointed to by 'fcp'
906        at the bios level.
907   =============================================================================
908*/
909
910int16_t ClsFile(struct fcb *fcp)
911{
912        register struct dirent *dp;
913
914#if DEBUGIT
915        if (fsdebug) {
916
917                printf("ClsFile($%08lX):  closing file\n", fcp);
918                SnapFCB(fcp);
919        }
920#endif
921
922        if (fcp->modefl & FC_OPN) {     /* is it open ? */
923
924                if (fcp->modefl & (FC_CR | FC_AP | FC_WR)) {    /* writing ? */
925
926                        if ((dp = _dsrch(&fcp->de))) {  /* locate the dirent */
927
928                                /* update the directory entry if it changed */
929
930                                if (memcmp(dp, &fcp->de, DENTSIZE)) {
931
932                                        memcpy(dp, &fcp->de, DENTSIZE);
933                                        _dirmod = TRUE;
934#if DEBUGIT
935        if (fsdebug) {
936
937                printf("ClsFile():  updated the directory.  FAT:\n");
938                mdump(_thefat, (char *)_thefat+127, _thefat);
939        }
940#endif
941
942                                }
943
944                        } else {
945
946#if DEBUGIT
947        if (fsdebug)
948                printf("ClsFile():  ERROR - can't find the directory entry\n");
949#endif
950
951                                errno = EIO;    /* can't find the entry */
952                                return(FAILURE);
953                        }
954                }
955
956#if DEBUGIT
957        if (fsdebug)
958                SnapFCB(fcp);
959#endif
960
961                return(SUCCESS);
962
963        } else {                /* not open */
964
965#if DEBUGIT
966        if (fsdebug)
967                printf("ClsFile():  ERROR - file not open\n");
968#endif
969
970                errno = EINVAL;
971                return(FAILURE);
972        }
973}
974
975/*
976   =============================================================================
977        _clsvol() -- close the volume
978   =============================================================================
979*/
980
981void _clsvol(void)
982{
983        if (_fatmod) {
984
985                _clsfat();
986
987#if     DEBUGIT
988        if (fsdebug)
989                printf("_clsvol():  modified FAT written\n");
990#endif
991        }
992
993        if (_dirmod) {
994
995                _clsdir();
996
997#if     DEBUGIT
998        if (fsdebug)
999                printf("_clsvol():  modified directory written\n");
1000#endif
1001        }
1002
1003        _bpbin = FALSE;
1004        _fatin = FALSE;
1005        _dirin = FALSE;
1006}
1007
1008/*
1009   =============================================================================
1010        fcbinit() -- initialize an FCB
1011   =============================================================================
1012*/
1013
1014int16_t fcbinit(int8_t *name, struct fcb *fcp)
1015{
1016        int8_t  tmpname[9], tmpext[4];
1017
1018        return(_inifcb(fcp, FilName(name, tmpname), FilExt(name, tmpext), 0));
1019}
1020
1021/*
1022   =============================================================================
1023        DelFile() -- Deletes the file named by fcb pointed to by 'fcp'.
1024   =============================================================================
1025*/
1026
1027int16_t DelFile(struct fcb *fcp)
1028{
1029#if     DEBUGIT
1030        if (fsdebug)
1031                printf("DelFile($%08.8lX):  deleting [%-.8s].[%-.3s]\n",
1032                        fcp, fcp->de.fname, fcp->de.fext);
1033#endif
1034
1035        if(_opnvol())                   /* open the volume */
1036                return(FAILURE);
1037
1038        if (DE_NULL EQ (_dptr = _dsrch(&fcp->de))) {    /* find the file */
1039
1040                errno = ENOENT;         /* can't find the file */
1041                return(FAILURE);
1042        }
1043
1044        if (_dptr->atrib & F_RDONLY) {
1045
1046                errno = EACCES;         /* can't delete an R/O file */
1047                return(FAILURE);
1048        }
1049
1050        if (_ftrnc(_dptr))              /* truncate the file to free its space  */
1051                return(FAILURE);
1052
1053        _dptr->fname[0] = (int8_t)0xE5; /* mark directory entry as free */
1054
1055#if     DEBUGIT
1056        if (fsdebug)
1057                printf("DelFile($%08.8lX):  file [%-.8s].[%-.3s] DELETED\n",
1058                        fcp, fcp->de.fname, fcp->de.fext);
1059#endif
1060
1061        return(SUCCESS);
1062}
1063
Note: See TracBrowser for help on using the repository browser.