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

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

Added missing includes and declarations.

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