source: buchla-68k/libcio/filesys.c@ 7258c6a

Last change on this file since 7258c6a was 7258c6a, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Use standard integer types.

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