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