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

Last change on this file was f261cc8, checked in by Thomas Lopatic <thomas@…>, 7 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.