1 /*-
2 * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/kernel.h>
32 #include <sys/proc.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/vnode.h>
37 #include <sys/mount.h>
38 #include <sys/namei.h>
39 #include <sys/malloc.h>
40 #include <sys/bio.h>
41 #include <sys/buf.h>
42
43 #include <fs/hpfs/hpfs.h>
44 #include <fs/hpfs/hpfsmount.h>
45 #include <fs/hpfs/hpfs_subr.h>
46
47 u_long
48 hpfs_checksum(
49 u_int8_t *object,
50 int size)
51 {
52 register int i;
53 u_long csum=0L;
54 for (i=0; i < size; i++) {
55 csum += (u_long) *object++;
56 csum = (csum << 7) + (csum >> (25));
57 }
58 return (csum);
59 }
60
61 void
62 hpfs_bmdeinit(
63 struct hpfsmount *hpmp)
64 {
65 struct buf *bp;
66 int i;
67
68 dprintf(("hpmp_bmdeinit: "));
69
70 if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) {
71 /*
72 * Write down BitMap.
73 */
74 for (i=0; i<hpmp->hpm_dbnum; i++) {
75 dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
76
77 bp = getblk(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
78 BMSIZE, 0, 0, 0);
79 clrbuf(bp);
80
81 bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
82 BMSIZE);
83
84 bwrite(bp);
85 }
86 }
87
88 FREE(hpmp->hpm_bitmap,M_HPFSMNT);
89 FREE(hpmp->hpm_bmind,M_HPFSMNT);
90
91 dprintf(("\n"));
92 }
93
94 /*
95 * Initialize BitMap management, includes calculation of
96 * available blocks number.
97 */
98 int
99 hpfs_bminit(
100 struct hpfsmount *hpmp)
101 {
102 struct buf *bp;
103 int error, i, k;
104 u_long dbavail;
105
106 dprintf(("hpfs_bminit: "));
107
108 hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
109
110 dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
111
112 MALLOC(hpmp->hpm_bmind, lsn_t *, hpmp->hpm_dbnum * sizeof(lsn_t),
113 M_HPFSMNT, M_WAITOK);
114
115 MALLOC(hpmp->hpm_bitmap, u_int8_t *, hpmp->hpm_dbnum * BMSIZE,
116 M_HPFSMNT, M_WAITOK);
117
118 error = bread(hpmp->hpm_devvp, hpmp->hpm_su.su_bitmap.lsn1,
119 ((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, NOCRED, &bp);
120 if (error) {
121 brelse(bp);
122 FREE(hpmp->hpm_bitmap, M_HPFSMNT);
123 FREE(hpmp->hpm_bmind, M_HPFSMNT);
124 dprintf((" error %d\n", error));
125 return (error);
126 }
127 bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
128
129 brelse(bp);
130
131 /*
132 * Read in all BitMap
133 */
134 for (i=0; i<hpmp->hpm_dbnum; i++) {
135 dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
136
137 error = bread(hpmp->hpm_devvp, hpmp->hpm_bmind[i],
138 BMSIZE, NOCRED, &bp);
139 if (error) {
140 brelse(bp);
141 FREE(hpmp->hpm_bitmap, M_HPFSMNT);
142 FREE(hpmp->hpm_bmind, M_HPFSMNT);
143 dprintf((" error %d\n", error));
144 return (error);
145 }
146 bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
147
148 brelse(bp);
149 }
150
151 /*
152 * Look througth BitMap and count free bits
153 */
154 dbavail = 0;
155 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
156 register u_int32_t mask;
157 for (k=0, mask=1; k < 32; k++, mask<<=1)
158 if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask)
159 dbavail ++;
160
161 }
162 hpmp->hpm_bavail = dbavail;
163
164 return (0);
165 }
166
167 int
168 hpfs_cmpfname (
169 struct hpfsmount *hpmp,
170 char * uname,
171 int ulen,
172 char * dname,
173 int dlen,
174 u_int16_t cp)
175 {
176 register int i, res;
177
178 for (i = 0; i < ulen && i < dlen; i++) {
179 res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) -
180 hpfs_toupper(hpmp, dname[i], cp);
181 if (res)
182 return res;
183 }
184 return (ulen - dlen);
185 }
186
187 int
188 hpfs_cpstrnnicmp (
189 struct hpfsmount *hpmp,
190 char * str1,
191 int str1len,
192 u_int16_t str1cp,
193 char * str2,
194 int str2len,
195 u_int16_t str2cp)
196 {
197 int i, res;
198
199 for (i = 0; i < str1len && i < str2len; i++) {
200 res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) -
201 (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
202 if (res)
203 return res;
204 }
205 return (str1len - str2len);
206 }
207
208
209 int
210 hpfs_cpload (
211 struct hpfsmount *hpmp,
212 struct cpiblk *cpibp,
213 struct cpdblk *cpdbp)
214 {
215 struct buf *bp;
216 struct cpdsec * cpdsp;
217 int error, i;
218
219 error = bread(hpmp->hpm_devvp, cpibp->b_cpdsec, DEV_BSIZE, NOCRED, &bp);
220 if (error) {
221 brelse(bp);
222 return (error);
223 }
224
225 cpdsp = (struct cpdsec *)bp->b_data;
226
227 for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
228 if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
229 bcopy(cpdsp->d_cpdblk + i, cpdbp,
230 sizeof(struct cpdblk));
231
232 brelse(bp);
233
234 return (0);
235 }
236 }
237
238 brelse(bp);
239
240 return (ENOENT);
241 }
242
243
244 /*
245 * Initialize Code Page information management.
246 * Load all copdepages in memory.
247 */
248 int
249 hpfs_cpinit (
250 struct mount *mp,
251 struct hpfsmount *hpmp)
252 {
253 struct buf *bp;
254 int error, i;
255 lsn_t lsn;
256 int cpicnt;
257 struct cpisec * cpisp;
258 struct cpiblk * cpibp;
259 struct cpdblk * cpdbp;
260
261 dprintf(("hpfs_cpinit: \n"));
262
263 error = vfs_copyopt(mp->mnt_optnew, "d2u", hpmp->hpm_d2u,
264 sizeof hpmp->hpm_d2u);
265 if (error == ENOENT)
266 for (i=0x0; i<0x80;i++)
267 hpmp->hpm_d2u[i] = i + 0x80;
268 else if (error)
269 return (error);
270
271 error = vfs_copyopt(mp->mnt_optnew, "u2d", hpmp->hpm_u2d,
272 sizeof hpmp->hpm_u2d);
273 if (error == ENOENT)
274 for (i=0x0; i<0x80;i++)
275 hpmp->hpm_u2d[i] = i + 0x80;
276 else if (error)
277 return (error);
278
279 cpicnt = hpmp->hpm_sp.sp_cpinum;
280
281 MALLOC(hpmp->hpm_cpdblk, struct cpdblk *,
282 cpicnt * sizeof(struct cpdblk), M_HPFSMNT, M_WAITOK);
283
284 cpdbp = hpmp->hpm_cpdblk;
285 lsn = hpmp->hpm_sp.sp_cpi;
286
287 while (cpicnt > 0) {
288 error = bread(hpmp->hpm_devvp, lsn, DEV_BSIZE, NOCRED, &bp);
289 if (error) {
290 brelse(bp);
291 return (error);
292 }
293
294 cpisp = (struct cpisec *)bp->b_data;
295
296 cpibp = cpisp->s_cpi;
297 for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
298 dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
299 cpibp->b_country, cpibp->b_cpid,
300 cpibp->b_vcpid));
301
302 error = hpfs_cpload(hpmp, cpibp, cpdbp);
303 if (error) {
304 brelse(bp);
305 return (error);
306 }
307 }
308 lsn = cpisp->s_next;
309 brelse(bp);
310 }
311
312 return (0);
313 }
314
315 int
316 hpfs_cpdeinit (
317 struct hpfsmount *hpmp)
318 {
319 dprintf(("hpmp_cpdeinit: "));
320 FREE(hpmp->hpm_cpdblk,M_HPFSMNT);
321 return (0);
322 }
323
324 /*
325 * Lookup for a run of blocks.
326 */
327 int
328 hpfs_bmlookup (
329 struct hpfsmount *hpmp,
330 u_long flags, /* 1 means we want right len blocks in run, not less */
331 lsn_t lsn, /* We want near this one */
332 u_long len, /* We want such long */
333 lsn_t *lsnp, /* We got here */
334 u_long *lenp) /* We got this long */
335 {
336 u_int32_t * bitmap;
337 register u_int32_t mask;
338 int i,k;
339 int cband, vcband;
340 u_int bandsz;
341 int count;
342
343 dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
344
345 if (lsn > hpmp->hpm_su.su_btotal) {
346 printf("hpfs_bmlookup: OUT OF VOLUME\n");
347 return ENOSPC;
348 }
349 if (len > hpmp->hpm_bavail) {
350 printf("hpfs_bmlookup: OUT OF SPACE\n");
351 return ENOSPC;
352 }
353 i = lsn >> 5;
354 k = lsn & 0x1F;
355 mask = 1 << k;
356 bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
357
358 if (*bitmap & mask) {
359 *lsnp = lsn;
360 *lenp = 0;
361 for (; k < 32; k++, mask<<=1) {
362 if (*bitmap & mask)
363 (*lenp) ++;
364 else {
365 if (flags & 1)
366 goto step2;
367 else
368 return (0);
369 }
370
371 if (*lenp == len)
372 return (0);
373 }
374
375 bitmap++;
376 i++;
377 for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
378 for (k=0, mask=1; k < 32; k++, mask<<=1) {
379 if (*bitmap & mask)
380 (*lenp) ++;
381 else {
382 if (flags & 1)
383 goto step2;
384 else
385 return (0);
386 }
387
388 if (*lenp == len)
389 return (0);
390 }
391 }
392 return (0);
393 }
394
395 step2:
396 /*
397 * Lookup all bands begining from cband, lookup for first block
398 */
399 cband = (lsn >> 14);
400 dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
401 cband, hpmp->hpm_dbnum));
402 for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
403 cband = cband % hpmp->hpm_dbnum;
404 bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
405 dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
406
407 bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
408 *lsnp = cband << 14;
409 *lenp = 0;
410 count = 0;
411 for (i=0; i < bandsz >> 5; i++, bitmap++) {
412 for (k=0, mask=1; k < 32; k++, mask<<=1) {
413 if (*bitmap & mask) {
414 if (count) {
415 (*lenp) ++;
416 } else {
417 count = 1;
418 *lsnp = (cband << 14) + (i << 5) + k;
419 *lenp = 1;
420 }
421 } else {
422 if ((*lenp) && !(flags & 1)) {
423 return (0);
424 } else {
425 count = 0;
426 }
427 }
428
429 if (*lenp == len)
430 return (0);
431 }
432 }
433 if (cband == hpmp->hpm_dbnum - 1) {
434 if ((*lenp) && !(flags & 1)) {
435 return (0);
436 } else {
437 count = 0;
438 }
439 }
440 }
441
442 return (ENOSPC);
443 }
444
445 /*
446 * Lookup a single free block. XXX Need locking on BitMap operations
447 * VERY STUPID ROUTINE!!!
448 */
449 int
450 hpfs_bmfblookup (
451 struct hpfsmount *hpmp,
452 lsn_t *lp)
453 {
454 u_int32_t * bitmap;
455 int i,k;
456
457 dprintf(("hpfs_bmfblookup: "));
458
459 bitmap = (u_int32_t *)hpmp->hpm_bitmap;
460 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
461 k = ffs(*bitmap);
462 if (k) {
463 *lp = (i << 5) + k - 1;
464 dprintf((" found: 0x%x\n",*lp));
465 return (0);
466 }
467 }
468
469 return (ENOSPC);
470 }
471
472 /*
473 * Mark contignous block of blocks.
474 */
475 int
476 hpfs_bmmark (
477 struct hpfsmount *hpmp,
478 lsn_t bn,
479 u_long bl,
480 int state)
481 {
482 u_int32_t * bitmap;
483 int i, didprint = 0;
484
485 dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
486
487 if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
488 printf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
489 return 0;
490 }
491 bitmap = (u_int32_t *)hpmp->hpm_bitmap;
492 bitmap += bn >> 5;
493
494 while (bl > 0) {
495 for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
496 if (state) {
497 if ( *bitmap & (1 << i)) {
498 if (!didprint) {
499 printf("hpfs_bmmark: ALREADY FREE\n");
500 didprint = 1;
501 }
502 } else
503 hpmp->hpm_bavail++;
504
505 *bitmap |= (1 << i);
506 } else {
507 if ((~(*bitmap)) & (1 << i)) {
508 if (!didprint) {
509 printf("hpfs_bmmark: ALREADY BUSY\n");
510 didprint = 1;
511 }
512 } else
513 hpmp->hpm_bavail--;
514
515 *bitmap &= ~(1 << i);
516 }
517 }
518 bn = 0;
519 bitmap++;
520 }
521
522 return (0);
523 }
524
525
526 int
527 hpfs_validateparent (
528 struct hpfsnode *hp)
529 {
530 struct hpfsnode *dhp;
531 struct vnode *dvp;
532 struct hpfsmount *hpmp = hp->h_hpmp;
533 struct buf *bp;
534 struct dirblk *dp;
535 struct hpfsdirent *dep;
536 lsn_t lsn, olsn;
537 int level, error;
538
539 dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
540 hp->h_no, hp->h_fn.fn_parent));
541
542 if (hp->h_no == hp->h_fn.fn_parent) {
543 dhp = hp;
544 } else {
545 error = VFS_VGET(hpmp->hpm_mp, hp->h_fn.fn_parent,
546 LK_EXCLUSIVE, &dvp);
547 if (error)
548 return (error);
549 dhp = VTOHP(dvp);
550 }
551
552 lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
553
554 olsn = 0;
555 level = 1;
556 bp = NULL;
557
558 dive:
559 dprintf(("[dive 0x%x] ", lsn));
560 if (bp != NULL)
561 brelse(bp);
562 error = bread(dhp->h_devvp, lsn, D_BSIZE, NOCRED, &bp);
563 if (error)
564 goto failed;
565
566 dp = (struct dirblk *) bp->b_data;
567 if (dp->d_magic != D_MAGIC) {
568 printf("hpfs_validatetimes: magic doesn't match\n");
569 error = EINVAL;
570 goto failed;
571 }
572
573 dep = D_DIRENT(dp);
574
575 if (olsn) {
576 dprintf(("[restore 0x%x] ", olsn));
577
578 while(!(dep->de_flag & DE_END) ) {
579 if((dep->de_flag & DE_DOWN) &&
580 (olsn == DE_DOWNLSN(dep)))
581 break;
582 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
583 }
584
585 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
586 if (dep->de_flag & DE_END)
587 goto blockdone;
588
589 if (hp->h_no == dep->de_fnode) {
590 dprintf(("[found] "));
591 goto readdone;
592 }
593
594 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
595 } else {
596 printf("hpfs_validatetimes: ERROR! oLSN not found\n");
597 error = EINVAL;
598 goto failed;
599 }
600 }
601
602 olsn = 0;
603
604 while(!(dep->de_flag & DE_END)) {
605 if(dep->de_flag & DE_DOWN) {
606 lsn = DE_DOWNLSN(dep);
607 level++;
608 goto dive;
609 }
610
611 if (hp->h_no == dep->de_fnode) {
612 dprintf(("[found] "));
613 goto readdone;
614 }
615
616 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
617 }
618
619 if(dep->de_flag & DE_DOWN) {
620 dprintf(("[enddive] "));
621 lsn = DE_DOWNLSN(dep);
622 level++;
623 goto dive;
624 }
625
626 blockdone:
627 dprintf(("[EOB] "));
628 olsn = lsn;
629 lsn = dp->d_parent;
630 level--;
631 dprintf(("[level %d] ", level));
632 if (level > 0)
633 goto dive; /* undive really */
634
635 goto failed;
636
637 readdone:
638 bcopy(dep->de_name,hp->h_name,dep->de_namelen);
639 hp->h_name[dep->de_namelen] = '\0';
640 hp->h_namelen = dep->de_namelen;
641 hp->h_ctime = dep->de_ctime;
642 hp->h_atime = dep->de_atime;
643 hp->h_mtime = dep->de_mtime;
644 hp->h_flag |= H_PARVALID;
645
646 dprintf(("[readdone]"));
647
648 failed:
649 dprintf(("\n"));
650 if (bp != NULL)
651 brelse(bp);
652 if (hp != dhp)
653 vput(dvp);
654
655 return (error);
656 }
657
658 struct timespec
659 hpfstimetounix (
660 u_long hptime)
661 {
662 struct timespec t;
663
664 t.tv_nsec = 0;
665 t.tv_sec = hptime;
666
667 return t;
668 }
669
670 /*
671 * Write down changes done to parent dir, these are only times for now.
672 * hpfsnode have to be locked.
673 */
674 int
675 hpfs_updateparent (
676 struct hpfsnode *hp)
677 {
678 struct hpfsnode *dhp;
679 struct vnode *dvp;
680 struct hpfsdirent *dep;
681 struct buf * bp;
682 int error;
683
684 dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no));
685
686 if (!(hp->h_flag & H_PARCHANGE))
687 return (0);
688
689 if (!(hp->h_flag & H_PARVALID)) {
690 error = hpfs_validateparent (hp);
691 if (error)
692 return (error);
693 }
694
695 if (hp->h_no == hp->h_fn.fn_parent) {
696 dhp = hp;
697 } else {
698 error = VFS_VGET(hp->h_hpmp->hpm_mp, hp->h_fn.fn_parent,
699 LK_EXCLUSIVE, &dvp);
700 if (error)
701 return (error);
702 dhp = VTOHP(dvp);
703 }
704
705 error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen,
706 &bp, &dep);
707 if (error) {
708 goto failed;
709 }
710
711 dep->de_atime = hp->h_atime;
712 dep->de_mtime = hp->h_mtime;
713 dep->de_size = hp->h_fn.fn_size;
714
715 bdwrite (bp);
716
717 hp->h_flag &= ~H_PARCHANGE;
718
719 error = 0;
720 failed:
721 if (hp != dhp)
722 vput(dvp);
723
724 return (0);
725 }
726
727 /*
728 * Write down on disk changes done to fnode. hpfsnode have to be locked.
729 */
730 int
731 hpfs_update (
732 struct hpfsnode *hp)
733 {
734 struct buf * bp;
735
736 dprintf(("hpfs_update(0x%x): \n", hp->h_no));
737
738 if (!(hp->h_flag & H_CHANGE))
739 return (0);
740
741 bp = getblk(hp->h_devvp, hp->h_no, FNODESIZE, 0, 0, 0);
742 clrbuf(bp);
743
744 bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode));
745 bdwrite (bp);
746
747 hp->h_flag &= ~H_CHANGE;
748
749 if (hp->h_flag & H_PARCHANGE)
750 return (hpfs_updateparent(hp));
751
752 return (0);
753 }
754
755 /*
756 * Truncate file to specifed size. hpfsnode have to be locked.
757 */
758 int
759 hpfs_truncate (
760 struct hpfsnode *hp,
761 u_long size)
762 {
763 struct hpfsmount *hpmp = hp->h_hpmp;
764 lsn_t newblen, oldblen;
765 int error, pf;
766
767 dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
768 hp->h_no, hp->h_fn.fn_size, size));
769
770 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
771 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
772
773 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
774
775 error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf);
776 if (error)
777 return (error);
778 if (pf) {
779 hp->h_fn.fn_ab.ab_flag = 0;
780 hp->h_fn.fn_ab.ab_freecnt = 0x8;
781 hp->h_fn.fn_ab.ab_busycnt = 0x0;
782 hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t);
783 }
784
785 hp->h_fn.fn_size = size;
786
787 hp->h_flag |= (H_CHANGE | H_PARCHANGE);
788
789 dprintf(("hpfs_truncate: successful\n"));
790
791 return (0);
792 }
793
794 /*
795 * Enlarge file to specifed size. hpfsnode have to be locked.
796 */
797 int
798 hpfs_extend (
799 struct hpfsnode *hp,
800 u_long size)
801 {
802 struct hpfsmount *hpmp = hp->h_hpmp;
803 lsn_t newblen, oldblen;
804 int error;
805
806 dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
807 hp->h_no, hp->h_fn.fn_size, size));
808
809 if (hpmp->hpm_bavail < 0x10)
810 return (ENOSPC);
811
812 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
813 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
814
815 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
816
817 error = hpfs_addextent(hpmp, hp, newblen - oldblen);
818 if (error) {
819 printf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error);
820 return (error);
821 }
822
823 hp->h_fn.fn_size = size;
824
825 hp->h_flag |= (H_CHANGE | H_PARCHANGE);
826
827 dprintf(("hpfs_extend: successful\n"));
828
829 return (0);
830 }
831
832 /*
833 * Read AlSec structure, and check if magic is valid.
834 * You don't need to brelse buf on error.
835 */
836 int
837 hpfs_breadstruct (
838 struct hpfsmount *hpmp,
839 lsn_t lsn,
840 u_int len,
841 u_int32_t magic,
842 struct buf **bpp)
843 {
844 struct buf *bp;
845 u_int32_t *mp;
846 int error;
847
848 dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn));
849
850 *bpp = NULL;
851
852 error = bread(hpmp->hpm_devvp, lsn, len, NOCRED, &bp);
853 if (error) {
854 brelse(bp);
855 return (error);
856 }
857 mp = (u_int32_t *) bp->b_data;
858 if (*mp != magic) {
859 brelse(bp);
860 printf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",
861 *mp, magic);
862 return (EINVAL);
863 }
864
865 *bpp = bp;
866
867 return (0);
868 }
869
Cache object: e9f03f61b4421aef9e0530de3bd0039a
|