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

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

Fixed argument order.

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