2 * Copyright (c) 1998, 1999 Semen Ustimenko (semenu@FreeBSD.org)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/sys/fs/hpfs/hpfs_subr.c,v 1.1 1999/12/09 19:09:59 semenu Exp $
27 * $DragonFly: src/sys/vfs/hpfs/hpfs_subr.c,v 1.8 2006/12/23 00:41:29 swildner Exp $
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
35 #include <sys/types.h>
37 #include <sys/vnode.h>
38 #include <sys/mount.h>
39 #include <sys/namei.h>
40 #include <sys/malloc.h>
46 #include "hpfsmount.h"
47 #include "hpfs_subr.h"
56 for (i=0; i < size; i++) {
57 csum += (u_long) *object++;
58 csum = (csum << 7) + (csum >> (25));
65 struct hpfsmount *hpmp)
70 dprintf(("hpmp_bmdeinit: "));
72 if (!(hpmp->hpm_mp->mnt_flag & MNT_RDONLY)) {
76 for (i=0; i<hpmp->hpm_dbnum; i++) {
77 dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
79 bp = getblk(hpmp->hpm_devvp,
80 dbtodoff(hpmp->hpm_bmind[i]),
84 bcopy(hpmp->hpm_bitmap + BMSIZE * i, bp->b_data,
91 FREE(hpmp->hpm_bitmap,M_HPFSMNT);
92 FREE(hpmp->hpm_bmind,M_HPFSMNT);
98 * Initialize BitMap management, includes calculation of
99 * available blocks number.
103 struct hpfsmount *hpmp)
109 dprintf(("hpfs_bminit: "));
111 hpmp->hpm_dbnum = (hpmp->hpm_su.su_btotal + 0x3FFF) / 0x4000;
113 dprintf(("0x%lx data bands, ", hpmp->hpm_dbnum));
115 MALLOC(hpmp->hpm_bmind, lsn_t *, hpmp->hpm_dbnum * sizeof(lsn_t),
116 M_HPFSMNT, M_WAITOK);
118 MALLOC(hpmp->hpm_bitmap, u_int8_t *, hpmp->hpm_dbnum * BMSIZE,
119 M_HPFSMNT, M_WAITOK);
121 error = bread(hpmp->hpm_devvp, dbtodoff(hpmp->hpm_su.su_bitmap.lsn1),
122 ((hpmp->hpm_dbnum + 0x7F) & ~(0x7F)) << 2, &bp);
125 FREE(hpmp->hpm_bitmap, M_HPFSMNT);
126 FREE(hpmp->hpm_bmind, M_HPFSMNT);
127 dprintf((" error %d\n", error));
130 bcopy(bp->b_data, hpmp->hpm_bmind, hpmp->hpm_dbnum * sizeof(lsn_t));
137 for (i=0; i<hpmp->hpm_dbnum; i++) {
138 dprintf(("[%d: 0x%x] ", i, hpmp->hpm_bmind[i]));
140 error = bread(hpmp->hpm_devvp, dbtodoff(hpmp->hpm_bmind[i]),
144 FREE(hpmp->hpm_bitmap, M_HPFSMNT);
145 FREE(hpmp->hpm_bmind, M_HPFSMNT);
146 dprintf((" error %d\n", error));
149 bcopy(bp->b_data, hpmp->hpm_bitmap + BMSIZE * i, BMSIZE);
155 * Look througth BitMap and count free bits
158 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++) {
160 for (k=0, mask=1; k < 32; k++, mask<<=1)
161 if(((u_int32_t *)hpmp->hpm_bitmap)[i] & mask)
165 hpmp->hpm_bavail = dbavail;
172 struct hpfsmount *hpmp,
181 for (i = 0; i < ulen && i < dlen; i++) {
182 res = hpfs_toupper(hpmp, hpfs_u2d(hpmp, uname[i]), cp) -
183 hpfs_toupper(hpmp, dname[i], cp);
187 return (ulen - dlen);
192 struct hpfsmount *hpmp,
202 for (i = 0; i < str1len && i < str2len; i++) {
203 res = (int)hpfs_toupper(hpmp, ((u_char *)str1)[i], str1cp) -
204 (int)hpfs_toupper(hpmp, ((u_char *)str2)[i], str2cp);
208 return (str1len - str2len);
214 struct hpfsmount *hpmp,
215 struct cpiblk *cpibp,
216 struct cpdblk *cpdbp)
219 struct cpdsec * cpdsp;
222 error = bread(hpmp->hpm_devvp, dbtodoff(cpibp->b_cpdsec), DEV_BSIZE, &bp);
228 cpdsp = (struct cpdsec *)bp->b_data;
230 for (i=cpdsp->d_cpfirst; i<cpdsp->d_cpcnt; i++) {
231 if (cpdsp->d_cpdblk[i].b_cpid == cpibp->b_cpid) {
232 bcopy(cpdsp->d_cpdblk + i, cpdbp,
233 sizeof(struct cpdblk));
248 * Initialize Code Page information management.
249 * Load all copdepages in memory.
253 struct hpfsmount *hpmp,
254 struct hpfs_args *argsp)
260 struct cpisec * cpisp;
261 struct cpiblk * cpibp;
262 struct cpdblk * cpdbp;
264 dprintf(("hpfs_cpinit: \n"));
266 if (argsp->flags & HPFSMNT_TABLES) {
267 bcopy(argsp->d2u, hpmp->hpm_d2u, sizeof(u_char) * 0x80);
268 bcopy(argsp->u2d, hpmp->hpm_u2d, sizeof(u_char) * 0x80);
270 for (i=0x0; i<0x80;i++) {
271 hpmp->hpm_d2u[i] = i + 0x80;
272 hpmp->hpm_u2d[i] = i + 0x80;
276 cpicnt = hpmp->hpm_sp.sp_cpinum;
278 MALLOC(hpmp->hpm_cpdblk, struct cpdblk *,
279 cpicnt * sizeof(struct cpdblk), M_HPFSMNT, M_WAITOK);
281 cpdbp = hpmp->hpm_cpdblk;
282 lsn = hpmp->hpm_sp.sp_cpi;
285 error = bread(hpmp->hpm_devvp, dbtodoff(lsn), DEV_BSIZE, &bp);
291 cpisp = (struct cpisec *)bp->b_data;
293 cpibp = cpisp->s_cpi;
294 for (i=0; i<cpisp->s_cpicnt; i++, cpicnt --, cpdbp++, cpibp++) {
295 dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
296 cpibp->b_country, cpibp->b_cpid,
299 error = hpfs_cpload(hpmp, cpibp, cpdbp);
314 struct hpfsmount *hpmp)
316 dprintf(("hpmp_cpdeinit: "));
317 FREE(hpmp->hpm_cpdblk,M_HPFSMNT);
322 * Lookup for a run of blocks.
326 struct hpfsmount *hpmp,
327 u_long flags, /* 1 means we want right len blocks in run, not less */
328 lsn_t lsn, /* We want near this one */
329 u_long len, /* We want such long */
330 lsn_t *lsnp, /* We got here */
331 u_long *lenp) /* We got this long */
340 dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn, len));
342 if (lsn > hpmp->hpm_su.su_btotal) {
343 kprintf("hpfs_bmlookup: OUT OF VOLUME\n");
346 if (len > hpmp->hpm_bavail) {
347 kprintf("hpfs_bmlookup: OUT OF SPACE\n");
353 bitmap = (u_int32_t *)hpmp->hpm_bitmap + i;
355 if (*bitmap & mask) {
358 for (; k < 32; k++, mask<<=1) {
374 for (; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
375 for (k=0, mask=1; k < 32; k++, mask<<=1) {
394 * Lookup all bands begining from cband, lookup for first block
397 dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
398 cband, hpmp->hpm_dbnum));
399 for (vcband = 0; vcband < hpmp->hpm_dbnum; vcband ++, cband++) {
400 cband = cband % hpmp->hpm_dbnum;
401 bandsz = min (hpmp->hpm_su.su_btotal - (cband << 14), 0x4000);
402 dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband, bandsz));
404 bitmap = (u_int32_t *)hpmp->hpm_bitmap + (cband << 9);
408 for (i=0; i < bandsz >> 5; i++, bitmap++) {
409 for (k=0, mask=1; k < 32; k++, mask<<=1) {
410 if (*bitmap & mask) {
415 *lsnp = (cband << 14) + (i << 5) + k;
419 if ((*lenp) && !(flags & 1)) {
430 if (cband == hpmp->hpm_dbnum - 1) {
431 if ((*lenp) && !(flags & 1)) {
443 * Lookup a single free block. XXX Need locking on BitMap operations
444 * VERY STUPID ROUTINE!!!
448 struct hpfsmount *hpmp,
454 dprintf(("hpfs_bmfblookup: "));
456 bitmap = (u_int32_t *)hpmp->hpm_bitmap;
457 for (i=0; i < hpmp->hpm_su.su_btotal >> 5; i++, bitmap++) {
460 *lp = (i << 5) + k - 1;
461 dprintf((" found: 0x%x\n",*lp));
470 * Mark contignous block of blocks.
474 struct hpfsmount *hpmp,
482 dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn,bl, state));
484 if ((bn > hpmp->hpm_su.su_btotal) || (bn+bl > hpmp->hpm_su.su_btotal)) {
485 kprintf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
488 bitmap = (u_int32_t *)hpmp->hpm_bitmap;
492 for (i = bn & 0x1F; (i < 0x20) && (bl > 0) ; i++, bl--) {
494 if ( *bitmap & (1 << i)) {
496 kprintf("hpfs_bmmark: ALREADY FREE\n");
504 if ((~(*bitmap)) & (1 << i)) {
506 kprintf("hpfs_bmmark: ALREADY BUSY\n");
512 *bitmap &= ~(1 << i);
524 hpfs_validateparent (
527 struct hpfsnode *dhp;
529 struct hpfsmount *hpmp = hp->h_hpmp;
532 struct hpfsdirent *dep;
536 dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
537 hp->h_no, hp->h_fn.fn_parent));
539 if (hp->h_no == hp->h_fn.fn_parent) {
542 error = VFS_VGET(hpmp->hpm_mp, NULL, hp->h_fn.fn_parent, &dvp);
548 lsn = ((alleaf_t *)dhp->h_fn.fn_abd)->al_lsn;
555 dprintf(("[dive 0x%x] ", lsn));
558 error = bread(dhp->h_devvp, dbtodoff(lsn), D_BSIZE, &bp);
562 dp = (struct dirblk *) bp->b_data;
563 if (dp->d_magic != D_MAGIC) {
564 kprintf("hpfs_validatetimes: magic doesn't match\n");
572 dprintf(("[restore 0x%x] ", olsn));
574 while(!(dep->de_flag & DE_END) ) {
575 if((dep->de_flag & DE_DOWN) &&
576 (olsn == DE_DOWNLSN(dep)))
578 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
581 if((dep->de_flag & DE_DOWN) && (olsn == DE_DOWNLSN(dep))) {
582 if (dep->de_flag & DE_END)
585 if (hp->h_no == dep->de_fnode) {
586 dprintf(("[found] "));
590 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
592 kprintf("hpfs_validatetimes: ERROR! oLSN not found\n");
600 while(!(dep->de_flag & DE_END)) {
601 if(dep->de_flag & DE_DOWN) {
602 lsn = DE_DOWNLSN(dep);
607 if (hp->h_no == dep->de_fnode) {
608 dprintf(("[found] "));
612 dep = (hpfsdirent_t *)((caddr_t)dep + dep->de_reclen);
615 if(dep->de_flag & DE_DOWN) {
616 dprintf(("[enddive] "));
617 lsn = DE_DOWNLSN(dep);
627 dprintf(("[level %d] ", level));
629 goto dive; /* undive really */
634 bcopy(dep->de_name,hp->h_name,dep->de_namelen);
635 hp->h_name[dep->de_namelen] = '\0';
636 hp->h_namelen = dep->de_namelen;
637 hp->h_ctime = dep->de_ctime;
638 hp->h_atime = dep->de_atime;
639 hp->h_mtime = dep->de_mtime;
640 hp->h_flag |= H_PARVALID;
642 dprintf(("[readdone]"));
667 * Write down changes done to parent dir, these are only times for now.
668 * hpfsnode have to be locked.
674 struct hpfsnode *dhp;
676 struct hpfsdirent *dep;
680 dprintf(("hpfs_updateparent(0x%x): \n", hp->h_no));
682 if (!(hp->h_flag & H_PARCHANGE))
685 if (!(hp->h_flag & H_PARVALID)) {
686 error = hpfs_validateparent (hp);
691 if (hp->h_no == hp->h_fn.fn_parent) {
694 error = VFS_VGET(hp->h_hpmp->hpm_mp, NULL,
695 hp->h_fn.fn_parent, &dvp);
701 error = hpfs_genlookupbyname (dhp, hp->h_name, hp->h_namelen,
707 dep->de_atime = hp->h_atime;
708 dep->de_mtime = hp->h_mtime;
709 dep->de_size = hp->h_fn.fn_size;
713 hp->h_flag &= ~H_PARCHANGE;
724 * Write down on disk changes done to fnode. hpfsnode have to be locked.
732 dprintf(("hpfs_update(0x%x): \n", hp->h_no));
734 if (!(hp->h_flag & H_CHANGE))
737 bp = getblk(hp->h_devvp, dbtodoff(hp->h_no), FNODESIZE, 0, 0);
740 bcopy (&hp->h_fn, bp->b_data, sizeof(struct fnode));
743 hp->h_flag &= ~H_CHANGE;
745 if (hp->h_flag & H_PARCHANGE)
746 return (hpfs_updateparent(hp));
752 * Truncate file to specifed size. hpfsnode have to be locked.
759 struct hpfsmount *hpmp = hp->h_hpmp;
760 lsn_t newblen, oldblen;
763 dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
764 hp->h_no, hp->h_fn.fn_size, size));
766 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
767 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
769 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
771 error = hpfs_truncatealblk (hpmp, &hp->h_fn.fn_ab, newblen, &pf);
775 hp->h_fn.fn_ab.ab_flag = 0;
776 hp->h_fn.fn_ab.ab_freecnt = 0x8;
777 hp->h_fn.fn_ab.ab_busycnt = 0x0;
778 hp->h_fn.fn_ab.ab_freeoff = sizeof(alblk_t);
781 hp->h_fn.fn_size = size;
783 hp->h_flag |= (H_CHANGE | H_PARCHANGE);
785 dprintf(("hpfs_truncate: successful\n"));
791 * Enlarge file to specifed size. hpfsnode have to be locked.
798 struct hpfsmount *hpmp = hp->h_hpmp;
799 lsn_t newblen, oldblen;
802 dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
803 hp->h_no, hp->h_fn.fn_size, size));
805 if (hpmp->hpm_bavail < 0x10)
808 newblen = (size + DEV_BSIZE - 1) >> DEV_BSHIFT;
809 oldblen = (hp->h_fn.fn_size + DEV_BSIZE - 1) >> DEV_BSHIFT;
811 dprintf(("blen: 0x%x -> 0x%x\n", oldblen, newblen));
813 error = hpfs_addextent(hpmp, hp, newblen - oldblen);
815 kprintf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error);
819 hp->h_fn.fn_size = size;
821 hp->h_flag |= (H_CHANGE | H_PARCHANGE);
823 dprintf(("hpfs_extend: successful\n"));
829 * Read AlSec structure, and check if magic is valid.
830 * You don't need to brelse buf on error.
834 struct hpfsmount *hpmp,
844 dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn));
848 error = bread(hpmp->hpm_devvp, dbtodoff(lsn), len, &bp);
853 mp = (u_int32_t *) bp->b_data;
856 kprintf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",