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

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

Added include files for global functions and variables.

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