ntfs_compr.c revision 77223
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: head/sys/fs/ntfs/ntfs_compr.c 77223 2001-05-26 11:57:45Z ru $
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
3854095Ssemenu#if defined(__NetBSD__)
3954095Ssemenu#include <miscfs/specfs/specdev.h>
4047060Ssemenu#endif
4143552Ssemenu
4277223Sru#include <fs/ntfs/ntfs.h>
4377223Sru#include <fs/ntfs/ntfs_compr.h>
4443552Ssemenu
4543552Ssemenu#define GET_UINT16(addr)	(*((u_int16_t *)(addr)))
4643552Ssemenu
4743552Ssemenuint
4843552Ssemenuntfs_uncompblock(
4943552Ssemenu	u_int8_t * buf,
5044142Ssemenu	u_int8_t * cbuf)
5143552Ssemenu{
5243552Ssemenu	u_int32_t       ctag;
5343552Ssemenu	int             len, dshift, lmask;
5443552Ssemenu	int             blen, boff;
5543552Ssemenu	int             i, j;
5643552Ssemenu	int             pos, cpos;
5743552Ssemenu
5843552Ssemenu	len = GET_UINT16(cbuf) & 0xFFF;
5943552Ssemenu	dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n",
6043552Ssemenu	    len, len, GET_UINT16(cbuf)));
6143552Ssemenu
6243552Ssemenu	if (!(GET_UINT16(cbuf) & 0x8000)) {
6343552Ssemenu		if ((len + 1) != NTFS_COMPBLOCK_SIZE) {
6443552Ssemenu			dprintf(("ntfs_uncompblock: len: %x instead of %d\n",
6543552Ssemenu			    len, 0xfff));
6643552Ssemenu		}
6743552Ssemenu		memcpy(buf, cbuf + 2, len + 1);
6843552Ssemenu		bzero(buf + len + 1, NTFS_COMPBLOCK_SIZE - 1 - len);
6943552Ssemenu		return len + 3;
7043552Ssemenu	}
7143552Ssemenu	cpos = 2;
7243552Ssemenu	pos = 0;
7343552Ssemenu	while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) {
7443552Ssemenu		ctag = cbuf[cpos++];
7543552Ssemenu		for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) {
7643552Ssemenu			if (ctag & 1) {
7743552Ssemenu				for (j = pos - 1, lmask = 0xFFF, dshift = 12;
7843552Ssemenu				     j >= 0x10; j >>= 1) {
7943552Ssemenu					dshift--;
8043552Ssemenu					lmask >>= 1;
8143552Ssemenu				}
8243552Ssemenu				boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift);
8343552Ssemenu				blen = 3 + (GET_UINT16(cbuf + cpos) & lmask);
8443552Ssemenu				for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) {
8543552Ssemenu					buf[pos] = buf[pos + boff];
8643552Ssemenu					pos++;
8743552Ssemenu				}
8843552Ssemenu				cpos += 2;
8943552Ssemenu			} else {
9043552Ssemenu				buf[pos++] = cbuf[cpos++];
9143552Ssemenu			}
9243552Ssemenu			ctag >>= 1;
9343552Ssemenu		}
9443552Ssemenu	}
9543552Ssemenu	return len + 3;
9643552Ssemenu}
9743552Ssemenu
9843552Ssemenuint
9943552Ssemenuntfs_uncompunit(
10043552Ssemenu	struct ntfsmount * ntmp,
10143552Ssemenu	u_int8_t * uup,
10244142Ssemenu	u_int8_t * cup)
10343552Ssemenu{
10443552Ssemenu	int             i;
10543552Ssemenu	int             off = 0;
10643552Ssemenu	int             new;
10743552Ssemenu
10843552Ssemenu	for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) {
10943552Ssemenu		new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off);
11043552Ssemenu		if (new == 0)
11143552Ssemenu			return (EINVAL);
11243552Ssemenu		off += new;
11343552Ssemenu	}
11443552Ssemenu	return (0);
11543552Ssemenu}
116