ntfs_compr.c revision 47060
1292309Srrs/*	$NetBSD: ntfs_compr.c,v 1.2 1999/05/06 15:43:18 christos Exp $	*/
2292309Srrs
3292309Srrs/*-
4292309Srrs * Copyright (c) 1998, 1999 Semen Ustimenko
5292309Srrs * All rights reserved.
6292309Srrs *
7292309Srrs * Redistribution and use in source and binary forms, with or without
8292309Srrs * modification, are permitted provided that the following conditions
9292309Srrs * are met:
10292309Srrs * 1. Redistributions of source code must retain the above copyright
11292309Srrs *    notice, this list of conditions and the following disclaimer.
12292309Srrs * 2. Redistributions in binary form must reproduce the above copyright
13292309Srrs *    notice, this list of conditions and the following disclaimer in the
14292309Srrs *    documentation and/or other materials provided with the distribution.
15292309Srrs *
16292309Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17292309Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18292309Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19292309Srrs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20292309Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21292309Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22292309Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23292309Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24292309Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25292309Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26292309Srrs * SUCH DAMAGE.
27292309Srrs *
28292309Srrs *	$Id: ntfs_compr.c,v 1.3 1999/04/20 21:06:43 semenu Exp $
29292309Srrs */
30292309Srrs
31292309Srrs#include <sys/param.h>
32292309Srrs#include <sys/systm.h>
33292309Srrs#include <sys/namei.h>
34292309Srrs#include <sys/proc.h>
35292309Srrs#include <sys/kernel.h>
36292309Srrs#include <sys/vnode.h>
37292309Srrs#include <sys/mount.h>
38292309Srrs#include <sys/buf.h>
39292309Srrs#include <sys/file.h>
40292309Srrs#include <sys/malloc.h>
41292309Srrs#ifdef __FreeBSD__
42292309Srrs#include <machine/clock.h>
43292309Srrs#endif
44292309Srrs
45292309Srrs#include <miscfs/specfs/specdev.h>
46292309Srrs
47292309Srrs#include <ntfs/ntfs.h>
48292309Srrs#include <ntfs/ntfs_compr.h>
49292309Srrs
50292309Srrs#define GET_UINT16(addr)	(*((u_int16_t *)(addr)))
51292309Srrs
52292309Srrsint
53292309Srrsntfs_uncompblock(
54292309Srrs	u_int8_t * buf,
55292309Srrs	u_int8_t * cbuf)
56292309Srrs{
57292309Srrs	u_int32_t       ctag;
58292309Srrs	int             len, dshift, lmask;
59292309Srrs	int             blen, boff;
60292309Srrs	int             i, j;
61292309Srrs	int             pos, cpos;
62292309Srrs
63292309Srrs	len = GET_UINT16(cbuf) & 0xFFF;
64292309Srrs	dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n",
65292309Srrs	    len, len, GET_UINT16(cbuf)));
66292309Srrs
67292309Srrs	if (!(GET_UINT16(cbuf) & 0x8000)) {
68292309Srrs		if ((len + 1) != NTFS_COMPBLOCK_SIZE) {
69292309Srrs			dprintf(("ntfs_uncompblock: len: %x instead of %d\n",
70292309Srrs			    len, 0xfff));
71292309Srrs		}
72292309Srrs		memcpy(buf, cbuf + 2, len + 1);
73292309Srrs		bzero(buf + len + 1, NTFS_COMPBLOCK_SIZE - 1 - len);
74292309Srrs		return len + 3;
75292309Srrs	}
76292309Srrs	cpos = 2;
77292309Srrs	pos = 0;
78292309Srrs	while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) {
79292309Srrs		ctag = cbuf[cpos++];
80292309Srrs		for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) {
81292309Srrs			if (ctag & 1) {
82292309Srrs				for (j = pos - 1, lmask = 0xFFF, dshift = 12;
83292309Srrs				     j >= 0x10; j >>= 1) {
84292309Srrs					dshift--;
85292309Srrs					lmask >>= 1;
86292309Srrs				}
87292309Srrs				boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift);
88292309Srrs				blen = 3 + (GET_UINT16(cbuf + cpos) & lmask);
89292309Srrs				for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) {
90292309Srrs					buf[pos] = buf[pos + boff];
91292309Srrs					pos++;
92292309Srrs				}
93292309Srrs				cpos += 2;
94292309Srrs			} else {
95292309Srrs				buf[pos++] = cbuf[cpos++];
96292309Srrs			}
97292309Srrs			ctag >>= 1;
98292309Srrs		}
99294535Sglebius	}
100292309Srrs	return len + 3;
101292309Srrs}
102292309Srrs
103292309Srrsint
104292309Srrsntfs_uncompunit(
105292309Srrs	struct ntfsmount * ntmp,
106292309Srrs	u_int8_t * uup,
107294931Sglebius	u_int8_t * cup)
108292309Srrs{
109292309Srrs	int             i;
110292309Srrs	int             off = 0;
111292309Srrs	int             new;
112292309Srrs
113292309Srrs	for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) {
114292309Srrs		new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off);
115292309Srrs		if (new == 0)
116292309Srrs			return (EINVAL);
117292309Srrs		off += new;
118292309Srrs	}
119292309Srrs	return (0);
120292309Srrs}
121292309Srrs