ntfs_compr.c revision 86927
1130167Sgad/*	$NetBSD: ntfs_compr.c,v 1.3 1999/07/26 14:02:31 jdolecek Exp $	*/
2130167Sgad
3130167Sgad/*-
4130167Sgad * Copyright (c) 1998, 1999 Semen Ustimenko
5130167Sgad * All rights reserved.
6130167Sgad *
7130167Sgad * Redistribution and use in source and binary forms, with or without
8130167Sgad * modification, are permitted provided that the following conditions
9130167Sgad * are met:
10130167Sgad * 1. Redistributions of source code must retain the above copyright
11130167Sgad *    notice, this list of conditions and the following disclaimer.
12130167Sgad * 2. Redistributions in binary form must reproduce the above copyright
13130167Sgad *    notice, this list of conditions and the following disclaimer in the
14130167Sgad *    documentation and/or other materials provided with the distribution.
15130167Sgad *
16130167Sgad * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17130167Sgad * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18130167Sgad * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19130167Sgad * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20130167Sgad * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21130167Sgad * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22130167Sgad * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23130167Sgad * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24130167Sgad * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25130167Sgad * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26130167Sgad * SUCH DAMAGE.
27130167Sgad *
28130167Sgad * $FreeBSD: head/sys/fs/ntfs/ntfs_compr.c 86927 2001-11-26 23:45:12Z jhb $
29130167Sgad */
30130167Sgad
3113244Sgraichen#include <sys/param.h>
3213244Sgraichen#include <sys/systm.h>
3313244Sgraichen#include <sys/namei.h>
3413244Sgraichen#include <sys/vnode.h>
3513244Sgraichen#include <sys/mount.h>
3659004Shm#include <sys/file.h>
3759004Shm
3859004Shm#include <fs/ntfs/ntfs.h>
3959004Shm#include <fs/ntfs/ntfs_compr.h>
4059004Shm
4159004Shm#define GET_UINT16(addr)	(*((u_int16_t *)(addr)))
4259004Shm
4359004Shmint
4459004Shmntfs_uncompblock(
4559004Shm	u_int8_t * buf,
4659004Shm	u_int8_t * cbuf)
4759004Shm{
4859004Shm	u_int32_t       ctag;
4959004Shm	int             len, dshift, lmask;
5013244Sgraichen	int             blen, boff;
5113244Sgraichen	int             i, j;
5259004Shm	int             pos, cpos;
5359004Shm
5413244Sgraichen	len = GET_UINT16(cbuf) & 0xFFF;
5513244Sgraichen	dprintf(("ntfs_uncompblock: block length: %d + 3, 0x%x,0x%04x\n",
56114601Sobrien	    len, len, GET_UINT16(cbuf)));
57114601Sobrien
5813244Sgraichen	if (!(GET_UINT16(cbuf) & 0x8000)) {
59130045Sgad		if ((len + 1) != NTFS_COMPBLOCK_SIZE) {
6013244Sgraichen			dprintf(("ntfs_uncompblock: len: %x instead of %d\n",
6196001Smaxim			    len, 0xfff));
62130167Sgad		}
6396001Smaxim		memcpy(buf, cbuf + 2, len + 1);
6496001Smaxim		bzero(buf + len + 1, NTFS_COMPBLOCK_SIZE - 1 - len);
6596001Smaxim		return len + 3;
66210372Ssimon	}
6730160Scharnier	cpos = 2;
6830160Scharnier	pos = 0;
6995999Smaxim	while ((cpos < len + 3) && (pos < NTFS_COMPBLOCK_SIZE)) {
70210372Ssimon		ctag = cbuf[cpos++];
7130160Scharnier		for (i = 0; (i < 8) && (pos < NTFS_COMPBLOCK_SIZE); i++) {
72111773Sgad			if (ctag & 1) {
73106905Ssobomax				for (j = pos - 1, lmask = 0xFFF, dshift = 12;
7430160Scharnier				     j >= 0x10; j >>= 1) {
7543071Swollman					dshift--;
7630160Scharnier					lmask >>= 1;
7730160Scharnier				}
7813244Sgraichen				boff = -1 - (GET_UINT16(cbuf + cpos) >> dshift);
79210372Ssimon				blen = 3 + (GET_UINT16(cbuf + cpos) & lmask);
8013244Sgraichen				for (j = 0; (j < blen) && (pos < NTFS_COMPBLOCK_SIZE); j++) {
8113244Sgraichen					buf[pos] = buf[pos + boff];
8243071Swollman					pos++;
8316240Salex				}
8413244Sgraichen				cpos += 2;
8543071Swollman			} else {
86119998Sgad				buf[pos++] = cbuf[cpos++];
8743071Swollman			}
88111768Sgad			ctag >>= 1;
89218127Smm		}
90218127Smm	}
91218127Smm	return len + 3;
92218127Smm}
93218127Smm
94218127Smmint
95218127Smmntfs_uncompunit(
96218127Smm	struct ntfsmount * ntmp,
97218127Smm	u_int8_t * uup,
98218127Smm	u_int8_t * cup)
99218127Smm{
100218127Smm	int             i;
101218127Smm	int             off = 0;
102218127Smm	int             new;
103218127Smm
104218127Smm	for (i = 0; i * NTFS_COMPBLOCK_SIZE < ntfs_cntob(NTFS_COMPUNIT_CL); i++) {
105218127Smm		new = ntfs_uncompblock(uup + i * NTFS_COMPBLOCK_SIZE, cup + off);
106218127Smm		if (new == 0)
107218127Smm			return (EINVAL);
108218127Smm		off += new;
109218127Smm	}
110218127Smm	return (0);
111218127Smm}
112218127Smm