154095Ssemenu/*	$NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $	*/
247060Ssemenu
343552Ssemenu/*-
443552Ssemenu * Copyright (c) 1998, 1999 Semen Ustimenko
543552Ssemenu * All rights reserved.
643552Ssemenu *
743552Ssemenu * Redistribution and use in source and binary forms, with or without
843552Ssemenu * modification, are permitted provided that the following conditions
943552Ssemenu * are met:
1043552Ssemenu * 1. Redistributions of source code must retain the above copyright
1143552Ssemenu *    notice, this list of conditions and the following disclaimer.
1243552Ssemenu * 2. Redistributions in binary form must reproduce the above copyright
1343552Ssemenu *    notice, this list of conditions and the following disclaimer in the
1443552Ssemenu *    documentation and/or other materials provided with the distribution.
1543552Ssemenu *
1643552Ssemenu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1743552Ssemenu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1843552Ssemenu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1943552Ssemenu * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2043552Ssemenu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2143552Ssemenu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2243552Ssemenu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2343552Ssemenu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2443552Ssemenu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2543552Ssemenu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2643552Ssemenu * SUCH DAMAGE.
2743552Ssemenu *
2850477Speter * $FreeBSD$
2943552Ssemenu */
3043552Ssemenu
3143552Ssemenu#include <sys/param.h>
3243552Ssemenu#include <sys/systm.h>
3343552Ssemenu#include <sys/namei.h>
3443552Ssemenu#include <sys/vnode.h>
3543552Ssemenu#include <sys/mount.h>
3643552Ssemenu#include <sys/file.h>
3754095Ssemenu
3877223Sru#include <fs/ntfs/ntfs.h>
3977223Sru#include <fs/ntfs/ntfs_compr.h>
4043552Ssemenu
4143552Ssemenu#define GET_UINT16(addr)	(*((u_int16_t *)(addr)))
4243552Ssemenu
4343552Ssemenuint
4443552Ssemenuntfs_uncompblock(
4543552Ssemenu	u_int8_t * buf,
4644142Ssemenu	u_int8_t * cbuf)
4743552Ssemenu{
4843552Ssemenu	u_int32_t       ctag;
4943552Ssemenu	int             len, dshift, lmask;
5043552Ssemenu	int             blen, boff;
5143552Ssemenu	int             i, j;
5243552Ssemenu	int             pos, cpos;
5343552Ssemenu
5443552Ssemenu	len = GET_UINT16(cbuf) & 0xFFF;
5543552Ssemenu	dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n",
5643552Ssemenu	    len, len, GET_UINT16(cbuf)));
5743552Ssemenu
5843552Ssemenu	if (!(GET_UINT16(cbuf) & 0x8000)) {
5943552Ssemenu		if ((len + 1) != NTFS_COMPBLOCK_SIZE) {
6043552Ssemenu			dprintf(("ntfs_uncompblock: len: %x instead of %d\n",
6143552Ssemenu			    len, 0xfff));
6243552Ssemenu		}
6343552Ssemenu		memcpy(buf, cbuf + 2, len + 1);
6443552Ssemenu		bzero(buf + len + 1, NTFS_COMPBLOCK_SIZE - 1 - len);
6543552Ssemenu		return len + 3;
6643552Ssemenu	}
6743552Ssemenu	cpos = 2;
6843552Ssemenu	pos = 0;
6943552Ssemenu	while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) {
7043552Ssemenu		ctag = cbuf[cpos++];
7143552Ssemenu		for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) {
7243552Ssemenu			if (ctag & 1) {
7343552Ssemenu				for (j = pos - 1, lmask = 0xFFF, dshift = 12;
7443552Ssemenu				     j >= 0x10; j >>= 1) {
7543552Ssemenu					dshift--;
7643552Ssemenu					lmask >>= 1;
7743552Ssemenu				}
7843552Ssemenu				boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift);
7943552Ssemenu				blen = 3 + (GET_UINT16(cbuf + cpos) & lmask);
8043552Ssemenu				for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) {
8143552Ssemenu					buf[pos] = buf[pos + boff];
8243552Ssemenu					pos++;
8343552Ssemenu				}
8443552Ssemenu				cpos += 2;
8543552Ssemenu			} else {
8643552Ssemenu				buf[pos++] = cbuf[cpos++];
8743552Ssemenu			}
8843552Ssemenu			ctag >>= 1;
8943552Ssemenu		}
9043552Ssemenu	}
9143552Ssemenu	return len + 3;
9243552Ssemenu}
9343552Ssemenu
9443552Ssemenuint
9543552Ssemenuntfs_uncompunit(
9643552Ssemenu	struct ntfsmount * ntmp,
9743552Ssemenu	u_int8_t * uup,
9844142Ssemenu	u_int8_t * cup)
9943552Ssemenu{
10043552Ssemenu	int             i;
10143552Ssemenu	int             off = 0;
10243552Ssemenu	int             new;
10343552Ssemenu
10443552Ssemenu	for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) {
10543552Ssemenu		new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off);
10643552Ssemenu		if (new == 0)
10743552Ssemenu			return (EINVAL);
10843552Ssemenu		off += new;
10943552Ssemenu	}
11043552Ssemenu	return (0);
11143552Ssemenu}
112