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>
44 #include "hpfsmount.h"
45 #include "hpfs_subr.h"
54 for (i
=0; i
< size
; i
++) {
55 csum
+= (u_long
) *object
++;
56 csum
= (csum
<< 7) + (csum
>> (25));
63 struct hpfsmount
*hpmp
)
68 dprintf(("hpmp_bmdeinit: "));
70 if (!(hpmp
->hpm_mp
->mnt_flag
& MNT_RDONLY
)) {
74 for (i
=0; i
<hpmp
->hpm_dbnum
; i
++) {
75 dprintf(("[%d: 0x%x] ", i
, hpmp
->hpm_bmind
[i
]));
77 bp
= getblk(hpmp
->hpm_devvp
,
78 dbtodoff(hpmp
->hpm_bmind
[i
]),
82 bcopy(hpmp
->hpm_bitmap
+ BMSIZE
* i
, bp
->b_data
,
89 FREE(hpmp
->hpm_bitmap
,M_HPFSMNT
);
90 FREE(hpmp
->hpm_bmind
,M_HPFSMNT
);
96 * Initialize BitMap management, includes calculation of
97 * available blocks number.
101 struct hpfsmount
*hpmp
)
107 dprintf(("hpfs_bminit: "));
109 hpmp
->hpm_dbnum
= (hpmp
->hpm_su
.su_btotal
+ 0x3FFF) / 0x4000;
111 dprintf(("0x%lx data bands, ", hpmp
->hpm_dbnum
));
113 MALLOC(hpmp
->hpm_bmind
, lsn_t
*, hpmp
->hpm_dbnum
* sizeof(lsn_t
),
114 M_HPFSMNT
, M_WAITOK
);
116 MALLOC(hpmp
->hpm_bitmap
, u_int8_t
*, hpmp
->hpm_dbnum
* BMSIZE
,
117 M_HPFSMNT
, M_WAITOK
);
119 error
= bread(hpmp
->hpm_devvp
, dbtodoff(hpmp
->hpm_su
.su_bitmap
.lsn1
),
120 ((hpmp
->hpm_dbnum
+ 0x7F) & ~(0x7F)) << 2, &bp
);
123 FREE(hpmp
->hpm_bitmap
, M_HPFSMNT
);
124 FREE(hpmp
->hpm_bmind
, M_HPFSMNT
);
125 dprintf((" error %d\n", error
));
128 bcopy(bp
->b_data
, hpmp
->hpm_bmind
, hpmp
->hpm_dbnum
* sizeof(lsn_t
));
135 for (i
=0; i
<hpmp
->hpm_dbnum
; i
++) {
136 dprintf(("[%d: 0x%x] ", i
, hpmp
->hpm_bmind
[i
]));
138 error
= bread(hpmp
->hpm_devvp
, dbtodoff(hpmp
->hpm_bmind
[i
]),
142 FREE(hpmp
->hpm_bitmap
, M_HPFSMNT
);
143 FREE(hpmp
->hpm_bmind
, M_HPFSMNT
);
144 dprintf((" error %d\n", error
));
147 bcopy(bp
->b_data
, hpmp
->hpm_bitmap
+ BMSIZE
* i
, BMSIZE
);
153 * Look througth BitMap and count free bits
156 for (i
=0; i
< hpmp
->hpm_su
.su_btotal
>> 5; i
++) {
158 for (k
=0, mask
=1; k
< 32; k
++, mask
<<=1)
159 if(((u_int32_t
*)hpmp
->hpm_bitmap
)[i
] & mask
)
163 hpmp
->hpm_bavail
= dbavail
;
170 struct hpfsmount
*hpmp
,
179 for (i
= 0; i
< ulen
&& i
< dlen
; i
++) {
180 res
= hpfs_toupper(hpmp
, hpfs_u2d(hpmp
, uname
[i
]), cp
) -
181 hpfs_toupper(hpmp
, dname
[i
], cp
);
185 return (ulen
- dlen
);
190 struct hpfsmount
*hpmp
,
200 for (i
= 0; i
< str1len
&& i
< str2len
; i
++) {
201 res
= (int)hpfs_toupper(hpmp
, ((u_char
*)str1
)[i
], str1cp
) -
202 (int)hpfs_toupper(hpmp
, ((u_char
*)str2
)[i
], str2cp
);
206 return (str1len
- str2len
);
212 struct hpfsmount
*hpmp
,
213 struct cpiblk
*cpibp
,
214 struct cpdblk
*cpdbp
)
217 struct cpdsec
* cpdsp
;
220 error
= bread(hpmp
->hpm_devvp
, dbtodoff(cpibp
->b_cpdsec
), DEV_BSIZE
, &bp
);
226 cpdsp
= (struct cpdsec
*)bp
->b_data
;
228 for (i
=cpdsp
->d_cpfirst
; i
<cpdsp
->d_cpcnt
; i
++) {
229 if (cpdsp
->d_cpdblk
[i
].b_cpid
== cpibp
->b_cpid
) {
230 bcopy(cpdsp
->d_cpdblk
+ i
, cpdbp
,
231 sizeof(struct cpdblk
));
246 * Initialize Code Page information management.
247 * Load all copdepages in memory.
251 struct hpfsmount
*hpmp
,
252 struct hpfs_args
*argsp
)
258 struct cpisec
* cpisp
;
259 struct cpiblk
* cpibp
;
260 struct cpdblk
* cpdbp
;
262 dprintf(("hpfs_cpinit: \n"));
264 if (argsp
->flags
& HPFSMNT_TABLES
) {
265 bcopy(argsp
->d2u
, hpmp
->hpm_d2u
, sizeof(u_char
) * 0x80);
266 bcopy(argsp
->u2d
, hpmp
->hpm_u2d
, sizeof(u_char
) * 0x80);
268 for (i
=0x0; i
<0x80;i
++) {
269 hpmp
->hpm_d2u
[i
] = i
+ 0x80;
270 hpmp
->hpm_u2d
[i
] = i
+ 0x80;
274 cpicnt
= hpmp
->hpm_sp
.sp_cpinum
;
276 MALLOC(hpmp
->hpm_cpdblk
, struct cpdblk
*,
277 cpicnt
* sizeof(struct cpdblk
), M_HPFSMNT
, M_WAITOK
);
279 cpdbp
= hpmp
->hpm_cpdblk
;
280 lsn
= hpmp
->hpm_sp
.sp_cpi
;
283 error
= bread(hpmp
->hpm_devvp
, dbtodoff(lsn
), DEV_BSIZE
, &bp
);
289 cpisp
= (struct cpisec
*)bp
->b_data
;
291 cpibp
= cpisp
->s_cpi
;
292 for (i
=0; i
<cpisp
->s_cpicnt
; i
++, cpicnt
--, cpdbp
++, cpibp
++) {
293 dprintf(("hpfs_cpinit: Country: %d, CP: %d (%d)\n",
294 cpibp
->b_country
, cpibp
->b_cpid
,
297 error
= hpfs_cpload(hpmp
, cpibp
, cpdbp
);
312 struct hpfsmount
*hpmp
)
314 dprintf(("hpmp_cpdeinit: "));
315 FREE(hpmp
->hpm_cpdblk
,M_HPFSMNT
);
320 * Lookup for a run of blocks.
324 struct hpfsmount
*hpmp
,
325 u_long flags
, /* 1 means we want right len blocks in run, not less */
326 lsn_t lsn
, /* We want near this one */
327 u_long len
, /* We want such long */
328 lsn_t
*lsnp
, /* We got here */
329 u_long
*lenp
) /* We got this long */
338 dprintf(("hpfs_bmlookup: lsn: 0x%x, len 0x%lx | Step1\n", lsn
, len
));
340 if (lsn
> hpmp
->hpm_su
.su_btotal
) {
341 kprintf("hpfs_bmlookup: OUT OF VOLUME\n");
344 if (len
> hpmp
->hpm_bavail
) {
345 kprintf("hpfs_bmlookup: OUT OF SPACE\n");
351 bitmap
= (u_int32_t
*)hpmp
->hpm_bitmap
+ i
;
353 if (*bitmap
& mask
) {
356 for (; k
< 32; k
++, mask
<<=1) {
372 for (; i
< hpmp
->hpm_su
.su_btotal
>> 5; i
++, bitmap
++) {
373 for (k
=0, mask
=1; k
< 32; k
++, mask
<<=1) {
392 * Lookup all bands begining from cband, lookup for first block
395 dprintf(("hpfs_bmlookup: Step2: band 0x%x (0x%lx)\n",
396 cband
, hpmp
->hpm_dbnum
));
397 for (vcband
= 0; vcband
< hpmp
->hpm_dbnum
; vcband
++, cband
++) {
398 cband
= cband
% hpmp
->hpm_dbnum
;
399 bandsz
= min (hpmp
->hpm_su
.su_btotal
- (cband
<< 14), 0x4000);
400 dprintf(("hpfs_bmlookup: band: %d, sz: 0x%x\n", cband
, bandsz
));
402 bitmap
= (u_int32_t
*)hpmp
->hpm_bitmap
+ (cband
<< 9);
406 for (i
=0; i
< bandsz
>> 5; i
++, bitmap
++) {
407 for (k
=0, mask
=1; k
< 32; k
++, mask
<<=1) {
408 if (*bitmap
& mask
) {
413 *lsnp
= (cband
<< 14) + (i
<< 5) + k
;
417 if ((*lenp
) && !(flags
& 1)) {
428 if (cband
== hpmp
->hpm_dbnum
- 1) {
429 if ((*lenp
) && !(flags
& 1)) {
441 * Lookup a single free block. XXX Need locking on BitMap operations
442 * VERY STUPID ROUTINE!!!
446 struct hpfsmount
*hpmp
,
452 dprintf(("hpfs_bmfblookup: "));
454 bitmap
= (u_int32_t
*)hpmp
->hpm_bitmap
;
455 for (i
=0; i
< hpmp
->hpm_su
.su_btotal
>> 5; i
++, bitmap
++) {
458 *lp
= (i
<< 5) + k
- 1;
459 dprintf((" found: 0x%x\n",*lp
));
468 * Mark contignous block of blocks.
472 struct hpfsmount
*hpmp
,
480 dprintf(("hpfs_bmmark(0x%x, 0x%lx, %d): \n",bn
,bl
, state
));
482 if ((bn
> hpmp
->hpm_su
.su_btotal
) || (bn
+bl
> hpmp
->hpm_su
.su_btotal
)) {
483 kprintf("hpfs_bmmark: MARKING OUT OF VOLUME\n");
486 bitmap
= (u_int32_t
*)hpmp
->hpm_bitmap
;
490 for (i
= bn
& 0x1F; (i
< 0x20) && (bl
> 0) ; i
++, bl
--) {
492 if ( *bitmap
& (1 << i
)) {
494 kprintf("hpfs_bmmark: ALREADY FREE\n");
502 if ((~(*bitmap
)) & (1 << i
)) {
504 kprintf("hpfs_bmmark: ALREADY BUSY\n");
510 *bitmap
&= ~(1 << i
);
522 hpfs_validateparent (
525 struct hpfsnode
*dhp
;
527 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
530 struct hpfsdirent
*dep
;
534 dprintf(("hpfs_validatetimes(0x%x): [parent: 0x%x] ",
535 hp
->h_no
, hp
->h_fn
.fn_parent
));
537 if (hp
->h_no
== hp
->h_fn
.fn_parent
) {
540 error
= VFS_VGET(hpmp
->hpm_mp
, hp
->h_fn
.fn_parent
, &dvp
);
546 lsn
= ((alleaf_t
*)dhp
->h_fn
.fn_abd
)->al_lsn
;
553 dprintf(("[dive 0x%x] ", lsn
));
556 error
= bread(dhp
->h_devvp
, dbtodoff(lsn
), D_BSIZE
, &bp
);
560 dp
= (struct dirblk
*) bp
->b_data
;
561 if (dp
->d_magic
!= D_MAGIC
) {
562 kprintf("hpfs_validatetimes: magic doesn't match\n");
570 dprintf(("[restore 0x%x] ", olsn
));
572 while(!(dep
->de_flag
& DE_END
) ) {
573 if((dep
->de_flag
& DE_DOWN
) &&
574 (olsn
== DE_DOWNLSN(dep
)))
576 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
579 if((dep
->de_flag
& DE_DOWN
) && (olsn
== DE_DOWNLSN(dep
))) {
580 if (dep
->de_flag
& DE_END
)
583 if (hp
->h_no
== dep
->de_fnode
) {
584 dprintf(("[found] "));
588 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
590 kprintf("hpfs_validatetimes: ERROR! oLSN not found\n");
598 while(!(dep
->de_flag
& DE_END
)) {
599 if(dep
->de_flag
& DE_DOWN
) {
600 lsn
= DE_DOWNLSN(dep
);
605 if (hp
->h_no
== dep
->de_fnode
) {
606 dprintf(("[found] "));
610 dep
= (hpfsdirent_t
*)((caddr_t
)dep
+ dep
->de_reclen
);
613 if(dep
->de_flag
& DE_DOWN
) {
614 dprintf(("[enddive] "));
615 lsn
= DE_DOWNLSN(dep
);
625 dprintf(("[level %d] ", level
));
627 goto dive
; /* undive really */
632 bcopy(dep
->de_name
,hp
->h_name
,dep
->de_namelen
);
633 hp
->h_name
[dep
->de_namelen
] = '\0';
634 hp
->h_namelen
= dep
->de_namelen
;
635 hp
->h_ctime
= dep
->de_ctime
;
636 hp
->h_atime
= dep
->de_atime
;
637 hp
->h_mtime
= dep
->de_mtime
;
638 hp
->h_flag
|= H_PARVALID
;
640 dprintf(("[readdone]"));
665 * Write down changes done to parent dir, these are only times for now.
666 * hpfsnode have to be locked.
672 struct hpfsnode
*dhp
;
674 struct hpfsdirent
*dep
;
678 dprintf(("hpfs_updateparent(0x%x): \n", hp
->h_no
));
680 if (!(hp
->h_flag
& H_PARCHANGE
))
683 if (!(hp
->h_flag
& H_PARVALID
)) {
684 error
= hpfs_validateparent (hp
);
689 if (hp
->h_no
== hp
->h_fn
.fn_parent
) {
692 error
= VFS_VGET(hp
->h_hpmp
->hpm_mp
, hp
->h_fn
.fn_parent
,
699 error
= hpfs_genlookupbyname (dhp
, hp
->h_name
, hp
->h_namelen
,
705 dep
->de_atime
= hp
->h_atime
;
706 dep
->de_mtime
= hp
->h_mtime
;
707 dep
->de_size
= hp
->h_fn
.fn_size
;
711 hp
->h_flag
&= ~H_PARCHANGE
;
722 * Write down on disk changes done to fnode. hpfsnode have to be locked.
730 dprintf(("hpfs_update(0x%x): \n", hp
->h_no
));
732 if (!(hp
->h_flag
& H_CHANGE
))
735 bp
= getblk(hp
->h_devvp
, dbtodoff(hp
->h_no
), FNODESIZE
, 0, 0);
738 bcopy (&hp
->h_fn
, bp
->b_data
, sizeof(struct fnode
));
741 hp
->h_flag
&= ~H_CHANGE
;
743 if (hp
->h_flag
& H_PARCHANGE
)
744 return (hpfs_updateparent(hp
));
750 * Truncate file to specifed size. hpfsnode have to be locked.
757 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
758 lsn_t newblen
, oldblen
;
761 dprintf(("hpfs_truncate(0x%x, 0x%x -> 0x%lx): ",
762 hp
->h_no
, hp
->h_fn
.fn_size
, size
));
764 newblen
= (size
+ DEV_BSIZE
- 1) >> DEV_BSHIFT
;
765 oldblen
= (hp
->h_fn
.fn_size
+ DEV_BSIZE
- 1) >> DEV_BSHIFT
;
767 dprintf(("blen: 0x%x -> 0x%x\n", oldblen
, newblen
));
769 error
= hpfs_truncatealblk (hpmp
, &hp
->h_fn
.fn_ab
, newblen
, &pf
);
773 hp
->h_fn
.fn_ab
.ab_flag
= 0;
774 hp
->h_fn
.fn_ab
.ab_freecnt
= 0x8;
775 hp
->h_fn
.fn_ab
.ab_busycnt
= 0x0;
776 hp
->h_fn
.fn_ab
.ab_freeoff
= sizeof(alblk_t
);
779 hp
->h_fn
.fn_size
= size
;
781 hp
->h_flag
|= (H_CHANGE
| H_PARCHANGE
);
783 dprintf(("hpfs_truncate: successful\n"));
789 * Enlarge file to specifed size. hpfsnode have to be locked.
796 struct hpfsmount
*hpmp
= hp
->h_hpmp
;
797 lsn_t newblen
, oldblen
;
800 dprintf(("hpfs_extend(0x%x, 0x%x -> 0x%lx): ",
801 hp
->h_no
, hp
->h_fn
.fn_size
, size
));
803 if (hpmp
->hpm_bavail
< 0x10)
806 newblen
= (size
+ DEV_BSIZE
- 1) >> DEV_BSHIFT
;
807 oldblen
= (hp
->h_fn
.fn_size
+ DEV_BSIZE
- 1) >> DEV_BSHIFT
;
809 dprintf(("blen: 0x%x -> 0x%x\n", oldblen
, newblen
));
811 error
= hpfs_addextent(hpmp
, hp
, newblen
- oldblen
);
813 kprintf("hpfs_extend: FAILED TO ADD EXTENT %d\n", error
);
817 hp
->h_fn
.fn_size
= size
;
819 hp
->h_flag
|= (H_CHANGE
| H_PARCHANGE
);
821 dprintf(("hpfs_extend: successful\n"));
827 * Read AlSec structure, and check if magic is valid.
828 * You don't need to brelse buf on error.
832 struct hpfsmount
*hpmp
,
842 dprintf(("hpfs_breadstruct: reading at 0x%x\n", lsn
));
846 error
= bread(hpmp
->hpm_devvp
, dbtodoff(lsn
), len
, &bp
);
851 mp
= (u_int32_t
*) bp
->b_data
;
854 kprintf("hpfs_breadstruct: MAGIC DOESN'T MATCH (0x%08x != 0x%08x)\n",