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