This source file includes following definitions.
- fatblock
- pcbmap
- fc_lookup
- fc_purge
- updatefats
- usemap_alloc
- usemap_free
- clusterfree
- fatentry
- fatchain
- chainlength
- chainalloc
- clusteralloc
- freeclusterchain
- fillinusemap
- extendfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 #include <sys/param.h>
55 #include <sys/systm.h>
56 #include <sys/buf.h>
57 #include <sys/file.h>
58 #include <sys/namei.h>
59 #include <sys/mount.h>
60 #include <sys/vnode.h>
61 #include <sys/errno.h>
62 #include <sys/dirent.h>
63
64
65
66
67 #include <msdosfs/bpb.h>
68 #include <msdosfs/msdosfsmount.h>
69 #include <msdosfs/direntry.h>
70 #include <msdosfs/denode.h>
71 #include <msdosfs/fat.h>
72
73
74
75
76 int fc_fileextends;
77 int fc_lfcempty;
78
79 int fc_bmapcalls;
80
81 #define LMMAX 20
82 int fc_lmdistance[LMMAX];
83
84 int fc_largedistance;
85
86 static void fatblock(struct msdosfsmount *, uint32_t, uint32_t *, uint32_t *,
87 uint32_t *);
88 void updatefats(struct msdosfsmount *, struct buf *, uint32_t);
89 static __inline void usemap_free(struct msdosfsmount *, uint32_t);
90 static __inline void usemap_alloc(struct msdosfsmount *, uint32_t);
91 static int fatchain(struct msdosfsmount *, uint32_t, uint32_t, uint32_t);
92 int chainlength(struct msdosfsmount *, uint32_t, uint32_t);
93 int chainalloc(struct msdosfsmount *, uint32_t, uint32_t, uint32_t, uint32_t *,
94 uint32_t *);
95
96 static void
97 fatblock(pmp, ofs, bnp, sizep, bop)
98 struct msdosfsmount *pmp;
99 uint32_t ofs;
100 uint32_t *bnp;
101 uint32_t *sizep;
102 uint32_t *bop;
103 {
104 uint32_t bn, size;
105
106 bn = ofs / pmp->pm_fatblocksize * pmp->pm_fatblocksec;
107 size = min(pmp->pm_fatblocksec, pmp->pm_FATsecs - bn) * DEV_BSIZE;
108 bn += pmp->pm_fatblk + pmp->pm_curfat * pmp->pm_FATsecs;
109
110 if (bnp)
111 *bnp = bn;
112 if (sizep)
113 *sizep = size;
114 if (bop)
115 *bop = ofs % pmp->pm_fatblocksize;
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 int
137 pcbmap(dep, findcn, bnp, cnp, sp)
138 struct denode *dep;
139 uint32_t findcn;
140 daddr64_t *bnp;
141 uint32_t *cnp;
142 int *sp;
143 {
144 int error;
145 uint32_t i;
146 uint32_t cn;
147 uint32_t prevcn = 0;
148 uint32_t byteoffset;
149 uint32_t bn;
150 uint32_t bo;
151 struct buf *bp = NULL;
152 uint32_t bp_bn = -1;
153 struct msdosfsmount *pmp = dep->de_pmp;
154 uint32_t bsize;
155
156 fc_bmapcalls++;
157
158
159
160
161
162 if (bnp == NULL && cnp == NULL && sp == NULL)
163 return (0);
164
165 cn = dep->de_StartCluster;
166
167
168
169
170
171
172 if (cn == MSDOSFSROOT) {
173 if (dep->de_Attributes & ATTR_DIRECTORY) {
174 if (de_cn2off(pmp, findcn) >= dep->de_FileSize) {
175 if (cnp)
176 *cnp = de_bn2cn(pmp, pmp->pm_rootdirsize);
177 return (E2BIG);
178 }
179 if (bnp)
180 *bnp = pmp->pm_rootdirblk + de_cn2bn(pmp, findcn);
181 if (cnp)
182 *cnp = MSDOSFSROOT;
183 if (sp)
184 *sp = min(pmp->pm_bpcluster,
185 dep->de_FileSize - de_cn2off(pmp, findcn));
186 return (0);
187 } else {
188 if (cnp)
189 *cnp = 0;
190 return (E2BIG);
191 }
192 }
193
194
195
196
197 if (sp)
198 *sp = pmp->pm_bpcluster;
199
200
201
202
203
204
205 i = 0;
206 fc_lookup(dep, findcn, &i, &cn);
207 if ((bn = findcn - i) >= LMMAX)
208 fc_largedistance++;
209 else
210 fc_lmdistance[bn]++;
211
212
213
214
215 for (; i < findcn; i++) {
216
217
218
219 if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
220 goto hiteof;
221 byteoffset = FATOFS(pmp, cn);
222 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
223 if (bn != bp_bn) {
224 if (bp)
225 brelse(bp);
226 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
227 if (error) {
228 brelse(bp);
229 return (error);
230 }
231 bp_bn = bn;
232 }
233 prevcn = cn;
234 if (bo >= bsize) {
235 if (bp)
236 brelse(bp);
237 return (EIO);
238 }
239 if (FAT32(pmp))
240 cn = getulong(&bp->b_data[bo]);
241 else
242 cn = getushort(&bp->b_data[bo]);
243 if (FAT12(pmp) && (prevcn & 1))
244 cn >>= 4;
245 cn &= pmp->pm_fatmask;
246
247
248
249
250
251
252
253 if ((cn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
254 cn |= ~pmp->pm_fatmask;
255 }
256
257 if (!MSDOSFSEOF(pmp, cn)) {
258 if (bp)
259 brelse(bp);
260 if (bnp)
261 *bnp = cntobn(pmp, cn);
262 if (cnp)
263 *cnp = cn;
264 fc_setcache(dep, FC_LASTMAP, i, cn);
265 return (0);
266 }
267
268 hiteof:;
269 if (cnp)
270 *cnp = i;
271 if (bp)
272 brelse(bp);
273
274 fc_setcache(dep, FC_LASTFC, i - 1, prevcn);
275 return (E2BIG);
276 }
277
278
279
280
281
282 void
283 fc_lookup(dep, findcn, frcnp, fsrcnp)
284 struct denode *dep;
285 uint32_t findcn;
286 uint32_t *frcnp;
287 uint32_t *fsrcnp;
288 {
289 int i;
290 uint32_t cn;
291 struct fatcache *closest = 0;
292
293 for (i = 0; i < FC_SIZE; i++) {
294 cn = dep->de_fc[i].fc_frcn;
295 if (cn != FCE_EMPTY && cn <= findcn) {
296 if (closest == 0 || cn > closest->fc_frcn)
297 closest = &dep->de_fc[i];
298 }
299 }
300 if (closest) {
301 *frcnp = closest->fc_frcn;
302 *fsrcnp = closest->fc_fsrcn;
303 }
304 }
305
306
307
308
309
310 void
311 fc_purge(dep, frcn)
312 struct denode *dep;
313 u_int frcn;
314 {
315 int i;
316 struct fatcache *fcp;
317
318 fcp = dep->de_fc;
319 for (i = 0; i < FC_SIZE; i++, fcp++) {
320 if (fcp->fc_frcn >= frcn)
321 fcp->fc_frcn = FCE_EMPTY;
322 }
323 }
324
325
326
327
328
329
330
331
332
333
334 void
335 updatefats(pmp, bp, fatbn)
336 struct msdosfsmount *pmp;
337 struct buf *bp;
338 uint32_t fatbn;
339 {
340 int i;
341 struct buf *bpn;
342
343 #ifdef MSDOSFS_DEBUG
344 printf("updatefats(pmp %08, buf %x, fatbn %ld)\n", pmp, bp, fatbn);
345 #endif
346
347
348
349
350 if (pmp->pm_fsinfo) {
351 uint32_t cn = pmp->pm_nxtfree;
352
353 if (pmp->pm_freeclustercount
354 && (pmp->pm_inusemap[cn / N_INUSEBITS]
355 & (1 << (cn % N_INUSEBITS)))) {
356
357
358
359
360 for (cn = 0; cn < pmp->pm_maxcluster; cn++)
361 if (pmp->pm_inusemap[cn / N_INUSEBITS] != (u_int)-1)
362 break;
363 pmp->pm_nxtfree = cn
364 + ffs(pmp->pm_inusemap[cn / N_INUSEBITS]
365 ^ (u_int)-1) - 1;
366 }
367 if (bread(pmp->pm_devvp, pmp->pm_fsinfo, fsi_size(pmp), NOCRED,
368 &bpn) != 0) {
369
370
371
372 pmp->pm_fsinfo = 0;
373 brelse(bpn);
374 } else {
375 struct fsinfo *fp = (struct fsinfo *)bpn->b_data;
376
377 putulong(fp->fsinfree, pmp->pm_freeclustercount);
378 putulong(fp->fsinxtfree, pmp->pm_nxtfree);
379 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
380 bwrite(bpn);
381 else
382 bdwrite(bpn);
383 }
384 }
385
386 if (pmp->pm_flags & MSDOSFS_FATMIRROR) {
387
388
389
390
391
392
393
394
395
396
397 for (i = 1; i < pmp->pm_FATs; i++) {
398 fatbn += pmp->pm_FATsecs;
399
400 bpn = getblk(pmp->pm_devvp, fatbn, bp->b_bcount, 0, 0);
401 bcopy(bp->b_data, bpn->b_data, bp->b_bcount);
402 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
403 bwrite(bpn);
404 else
405 bdwrite(bpn);
406 }
407 }
408
409
410
411
412 if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT)
413 bwrite(bp);
414 else
415 bdwrite(bp);
416
417
418
419 }
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440 static __inline void
441 usemap_alloc(pmp, cn)
442 struct msdosfsmount *pmp;
443 uint32_t cn;
444 {
445
446 pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
447 pmp->pm_freeclustercount--;
448 }
449
450 static __inline void
451 usemap_free(pmp, cn)
452 struct msdosfsmount *pmp;
453 uint32_t cn;
454 {
455
456 pmp->pm_freeclustercount++;
457 pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
458 }
459
460 int
461 clusterfree(pmp, cluster, oldcnp)
462 struct msdosfsmount *pmp;
463 uint32_t cluster;
464 uint32_t *oldcnp;
465 {
466 int error;
467 uint32_t oldcn;
468
469 usemap_free(pmp, cluster);
470 error = fatentry(FAT_GET_AND_SET, pmp, cluster, &oldcn, MSDOSFSFREE);
471 if (error) {
472 usemap_alloc(pmp, cluster);
473 return (error);
474 }
475
476
477
478
479
480 if (oldcnp)
481 *oldcnp = oldcn;
482 return (0);
483 }
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504 int
505 fatentry(function, pmp, cn, oldcontents, newcontents)
506 int function;
507 struct msdosfsmount *pmp;
508 uint32_t cn;
509 uint32_t *oldcontents;
510 uint32_t newcontents;
511 {
512 int error;
513 uint32_t readcn;
514 uint32_t bn, bo, bsize, byteoffset;
515 struct buf *bp;
516
517 #ifdef MSDOSFS_DEBUG
518 printf("fatentry(func %d, pmp %08x, clust %d, oldcon %08x, newcon %d)\n",
519 function, pmp, cn, oldcontents, newcontents);
520 #endif
521
522 #ifdef DIAGNOSTIC
523
524
525
526 if ((function & (FAT_SET | FAT_GET)) == 0) {
527 printf("fatentry(): function code doesn't specify get or set\n");
528 return (EINVAL);
529 }
530
531
532
533
534
535 if ((function & FAT_GET) && oldcontents == NULL) {
536 printf("fatentry(): get function with no place to put result\n");
537 return (EINVAL);
538 }
539 #endif
540
541
542
543
544 if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster)
545 return (EINVAL);
546
547 byteoffset = FATOFS(pmp, cn);
548 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
549 if ((error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp)) != 0) {
550 brelse(bp);
551 return (error);
552 }
553
554 if (function & FAT_GET) {
555 if (FAT32(pmp))
556 readcn = getulong(&bp->b_data[bo]);
557 else
558 readcn = getushort(&bp->b_data[bo]);
559 if (FAT12(pmp) && (cn & 1))
560 readcn >>= 4;
561 readcn &= pmp->pm_fatmask;
562
563 if ((readcn | ~pmp->pm_fatmask) >= CLUST_RSRVD)
564 readcn |= ~pmp->pm_fatmask;
565 *oldcontents = readcn;
566 }
567 if (function & FAT_SET) {
568 switch (pmp->pm_fatmask) {
569 case FAT12_MASK:
570 readcn = getushort(&bp->b_data[bo]);
571 if (cn & 1) {
572 readcn &= 0x000f;
573 readcn |= newcontents << 4;
574 } else {
575 readcn &= 0xf000;
576 readcn |= newcontents & 0xfff;
577 }
578 putushort(&bp->b_data[bo], readcn);
579 break;
580 case FAT16_MASK:
581 putushort(&bp->b_data[bo], newcontents);
582 break;
583 case FAT32_MASK:
584
585
586
587
588 readcn = getulong(&bp->b_data[bo]);
589 readcn &= ~FAT32_MASK;
590 readcn |= newcontents & FAT32_MASK;
591 putulong(&bp->b_data[bo], readcn);
592 break;
593 }
594 updatefats(pmp, bp, bn);
595 bp = NULL;
596 pmp->pm_fmod = 1;
597 }
598 if (bp)
599 brelse(bp);
600 return (0);
601 }
602
603
604
605
606
607
608
609
610
611 static int
612 fatchain(pmp, start, count, fillwith)
613 struct msdosfsmount *pmp;
614 uint32_t start;
615 uint32_t count;
616 uint32_t fillwith;
617 {
618 int error;
619 uint32_t bn, bo, bsize, byteoffset, readcn, newc;
620 struct buf *bp;
621
622 #ifdef MSDOSFS_DEBUG
623 printf("fatchain(pmp %08x, start %d, count %d, fillwith %d)\n",
624 pmp, start, count, fillwith);
625 #endif
626
627
628
629 if (start < CLUST_FIRST || start + count - 1 > pmp->pm_maxcluster)
630 return (EINVAL);
631
632 while (count > 0) {
633 byteoffset = FATOFS(pmp, start);
634 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
635 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
636 if (error) {
637 brelse(bp);
638 return (error);
639 }
640 while (count > 0) {
641 start++;
642 newc = --count > 0 ? start : fillwith;
643 switch (pmp->pm_fatmask) {
644 case FAT12_MASK:
645 readcn = getushort(&bp->b_data[bo]);
646 if (start & 1) {
647 readcn &= 0xf000;
648 readcn |= newc & 0xfff;
649 } else {
650 readcn &= 0x000f;
651 readcn |= newc << 4;
652 }
653 putushort(&bp->b_data[bo], readcn);
654 bo++;
655 if (!(start & 1))
656 bo++;
657 break;
658 case FAT16_MASK:
659 putushort(&bp->b_data[bo], newc);
660 bo += 2;
661 break;
662 case FAT32_MASK:
663 readcn = getulong(&bp->b_data[bo]);
664 readcn &= ~pmp->pm_fatmask;
665 readcn |= newc & pmp->pm_fatmask;
666 putulong(&bp->b_data[bo], readcn);
667 bo += 4;
668 break;
669 }
670 if (bo >= bsize)
671 break;
672 }
673 updatefats(pmp, bp, bn);
674 }
675 pmp->pm_fmod = 1;
676 return (0);
677 }
678
679
680
681
682
683
684
685
686 int
687 chainlength(pmp, start, count)
688 struct msdosfsmount *pmp;
689 uint32_t start;
690 uint32_t count;
691 {
692 uint32_t idx, max_idx;
693 u_int map;
694 uint32_t len;
695
696 max_idx = pmp->pm_maxcluster / N_INUSEBITS;
697 idx = start / N_INUSEBITS;
698 start %= N_INUSEBITS;
699 map = pmp->pm_inusemap[idx];
700 map &= ~((1 << start) - 1);
701 if (map) {
702 len = ffs(map) - 1 - start;
703 return (len > count ? count : len);
704 }
705 len = N_INUSEBITS - start;
706 if (len >= count)
707 return (count);
708 while (++idx <= max_idx) {
709 if (len >= count)
710 break;
711 if ((map = pmp->pm_inusemap[idx]) != 0) {
712 len += ffs(map) - 1;
713 break;
714 }
715 len += N_INUSEBITS;
716 }
717 return (len > count ? count : len);
718 }
719
720
721
722
723
724
725
726
727
728
729
730
731 int
732 chainalloc(pmp, start, count, fillwith, retcluster, got)
733 struct msdosfsmount *pmp;
734 uint32_t start;
735 uint32_t count;
736 uint32_t fillwith;
737 uint32_t *retcluster;
738 uint32_t *got;
739 {
740 int error;
741 uint32_t cl, n;
742
743 for (cl = start, n = count; n-- > 0;)
744 usemap_alloc(pmp, cl++);
745 if ((error = fatchain(pmp, start, count, fillwith)) != 0)
746 return (error);
747 #ifdef MSDOSFS_DEBUG
748 printf("clusteralloc(): allocated cluster chain at %d (%d clusters)\n",
749 start, count);
750 #endif
751 if (retcluster)
752 *retcluster = start;
753 if (got)
754 *got = count;
755 return (0);
756 }
757
758
759
760
761
762
763
764
765
766
767
768
769 int
770 clusteralloc(pmp, start, count, fillwith, retcluster, got)
771 struct msdosfsmount *pmp;
772 uint32_t start;
773 uint32_t count;
774 uint32_t fillwith;
775 uint32_t *retcluster;
776 uint32_t *got;
777 {
778 uint32_t idx;
779 uint32_t len, newst, foundl, cn, l;
780 uint32_t foundcn = 0;
781 u_int map;
782
783 #ifdef MSDOSFS_DEBUG
784 printf("clusteralloc(): find %d clusters\n",count);
785 #endif
786 if (start) {
787 if ((len = chainlength(pmp, start, count)) >= count)
788 return (chainalloc(pmp, start, count, fillwith, retcluster, got));
789 } else {
790
791
792
793 struct timeval tv;
794
795 microtime(&tv);
796 start = (tv.tv_usec >> 10) | tv.tv_usec;
797 len = 0;
798 }
799
800
801
802
803
804 newst = (start * 1103515245 + 12345) % (pmp->pm_maxcluster + 1);
805 foundl = 0;
806
807 for (cn = newst; cn <= pmp->pm_maxcluster;) {
808 idx = cn / N_INUSEBITS;
809 map = pmp->pm_inusemap[idx];
810 map |= (1 << (cn % N_INUSEBITS)) - 1;
811 if (map != (u_int)-1) {
812 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
813 if ((l = chainlength(pmp, cn, count)) >= count)
814 return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
815 if (l > foundl) {
816 foundcn = cn;
817 foundl = l;
818 }
819 cn += l + 1;
820 continue;
821 }
822 cn += N_INUSEBITS - cn % N_INUSEBITS;
823 }
824 for (cn = 0; cn < newst;) {
825 idx = cn / N_INUSEBITS;
826 map = pmp->pm_inusemap[idx];
827 map |= (1 << (cn % N_INUSEBITS)) - 1;
828 if (map != (u_int)-1) {
829 cn = idx * N_INUSEBITS + ffs(map^(u_int)-1) - 1;
830 if ((l = chainlength(pmp, cn, count)) >= count)
831 return (chainalloc(pmp, cn, count, fillwith, retcluster, got));
832 if (l > foundl) {
833 foundcn = cn;
834 foundl = l;
835 }
836 cn += l + 1;
837 continue;
838 }
839 cn += N_INUSEBITS - cn % N_INUSEBITS;
840 }
841
842 if (!foundl)
843 return (ENOSPC);
844
845 if (len)
846 return (chainalloc(pmp, start, len, fillwith, retcluster, got));
847 else
848 return (chainalloc(pmp, foundcn, foundl, fillwith, retcluster, got));
849 }
850
851
852
853
854
855
856
857
858
859
860 int
861 freeclusterchain(pmp, cluster)
862 struct msdosfsmount *pmp;
863 uint32_t cluster;
864 {
865 int error;
866 struct buf *bp = NULL;
867 uint32_t bn, bo, bsize, byteoffset;
868 uint32_t readcn, lbn = -1;
869
870 while (cluster >= CLUST_FIRST && cluster <= pmp->pm_maxcluster) {
871 byteoffset = FATOFS(pmp, cluster);
872 fatblock(pmp, byteoffset, &bn, &bsize, &bo);
873 if (lbn != bn) {
874 if (bp)
875 updatefats(pmp, bp, lbn);
876 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
877 if (error) {
878 brelse(bp);
879 return (error);
880 }
881 lbn = bn;
882 }
883 usemap_free(pmp, cluster);
884 switch (pmp->pm_fatmask) {
885 case FAT12_MASK:
886 readcn = getushort(&bp->b_data[bo]);
887 if (cluster & 1) {
888 cluster = readcn >> 4;
889 readcn &= 0x000f;
890 readcn |= MSDOSFSFREE << 4;
891 } else {
892 cluster = readcn;
893 readcn &= 0xf000;
894 readcn |= MSDOSFSFREE & 0xfff;
895 }
896 putushort(&bp->b_data[bo], readcn);
897 break;
898 case FAT16_MASK:
899 cluster = getushort(&bp->b_data[bo]);
900 putushort(&bp->b_data[bo], MSDOSFSFREE);
901 break;
902 case FAT32_MASK:
903 cluster = getulong(&bp->b_data[bo]);
904 putulong(&bp->b_data[bo],
905 (MSDOSFSFREE & FAT32_MASK) | (cluster & ~FAT32_MASK));
906 break;
907 }
908 cluster &= pmp->pm_fatmask;
909 if ((cluster | ~pmp->pm_fatmask) >= CLUST_RSRVD)
910 cluster |= pmp->pm_fatmask;
911 }
912 if (bp)
913 updatefats(pmp, bp, bn);
914 return (0);
915 }
916
917
918
919
920
921 int
922 fillinusemap(pmp)
923 struct msdosfsmount *pmp;
924 {
925 struct buf *bp = NULL;
926 uint32_t cn, readcn;
927 int error;
928 uint32_t bn, bo, bsize, byteoffset;
929
930
931
932
933
934 for (cn = 0; cn < (pmp->pm_maxcluster + N_INUSEBITS) / N_INUSEBITS; cn++)
935 pmp->pm_inusemap[cn] = (u_int)-1;
936
937
938
939
940
941
942 pmp->pm_freeclustercount = 0;
943 for (cn = CLUST_FIRST; cn <= pmp->pm_maxcluster; cn++) {
944 byteoffset = FATOFS(pmp, cn);
945 bo = byteoffset % pmp->pm_fatblocksize;
946 if (!bo || !bp) {
947
948 if (bp)
949 brelse(bp);
950 fatblock(pmp, byteoffset, &bn, &bsize, NULL);
951 error = bread(pmp->pm_devvp, bn, bsize, NOCRED, &bp);
952 if (error) {
953 brelse(bp);
954 return (error);
955 }
956 }
957 if (FAT32(pmp))
958 readcn = getulong(&bp->b_data[bo]);
959 else
960 readcn = getushort(&bp->b_data[bo]);
961 if (FAT12(pmp) && (cn & 1))
962 readcn >>= 4;
963 readcn &= pmp->pm_fatmask;
964
965 if (readcn == 0)
966 usemap_free(pmp, cn);
967 }
968 brelse(bp);
969 return (0);
970 }
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987 int
988 extendfile(dep, count, bpp, ncp, flags)
989 struct denode *dep;
990 uint32_t count;
991 struct buf **bpp;
992 uint32_t *ncp;
993 int flags;
994 {
995 int error;
996 uint32_t frcn;
997 uint32_t cn, got;
998 struct msdosfsmount *pmp = dep->de_pmp;
999 struct buf *bp;
1000
1001
1002
1003
1004 if (dep->de_StartCluster == MSDOSFSROOT
1005 && (dep->de_Attributes & ATTR_DIRECTORY)) {
1006 printf("extendfile(): attempt to extend root directory\n");
1007 return (ENOSPC);
1008 }
1009
1010
1011
1012
1013
1014 fc_fileextends++;
1015 if (dep->de_fc[FC_LASTFC].fc_frcn == FCE_EMPTY &&
1016 dep->de_StartCluster != 0) {
1017 fc_lfcempty++;
1018 error = pcbmap(dep, 0xffff, 0, &cn, 0);
1019
1020 if (error != E2BIG)
1021 return (error);
1022 }
1023
1024 while (count > 0) {
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034 if (dep->de_StartCluster == 0)
1035 cn = 0;
1036 else
1037 cn = dep->de_fc[FC_LASTFC].fc_fsrcn + 1;
1038 error = clusteralloc(pmp, cn, count, CLUST_EOFE, &cn, &got);
1039 if (error)
1040 return (error);
1041
1042 count -= got;
1043
1044
1045
1046
1047
1048 if (ncp) {
1049 *ncp = cn;
1050 ncp = NULL;
1051 }
1052
1053 if (dep->de_StartCluster == 0) {
1054 dep->de_StartCluster = cn;
1055 frcn = 0;
1056 } else {
1057 error = fatentry(FAT_SET, pmp,
1058 dep->de_fc[FC_LASTFC].fc_fsrcn,
1059 0, cn);
1060 if (error) {
1061 clusterfree(pmp, cn, NULL);
1062 return (error);
1063 }
1064 frcn = dep->de_fc[FC_LASTFC].fc_frcn + 1;
1065 }
1066
1067
1068
1069
1070
1071 fc_setcache(dep, FC_LASTFC, frcn + got - 1, cn + got - 1);
1072
1073 if (flags & DE_CLEAR) {
1074 while (got-- > 0) {
1075
1076
1077
1078 if (dep->de_Attributes & ATTR_DIRECTORY)
1079 bp = getblk(pmp->pm_devvp, cntobn(pmp, cn++),
1080 pmp->pm_bpcluster, 0, 0);
1081 else {
1082 bp = getblk(DETOV(dep), de_cn2bn(pmp, frcn++),
1083 pmp->pm_bpcluster, 0, 0);
1084
1085
1086
1087 if (pcbmap(dep,
1088 de_bn2cn(pmp, bp->b_lblkno),
1089 &bp->b_blkno, 0, 0))
1090 bp->b_blkno = -1;
1091 if (bp->b_blkno == -1)
1092 panic("extendfile: pcbmap");
1093 }
1094 clrbuf(bp);
1095 if (bpp) {
1096 *bpp = bp;
1097 bpp = NULL;
1098 } else
1099 bdwrite(bp);
1100 }
1101 }
1102 }
1103
1104 return (0);
1105 }