Home | History | Annotate | Line # | Download | only in hpcboot
file_manager.cpp revision 1.1.4.1
      1  1.1.4.1  nathanw /* -*-C++-*-	$NetBSD: file_manager.cpp,v 1.1.4.1 2001/06/21 19:22:43 nathanw Exp $	*/
      2      1.1      uch 
      3      1.1      uch /*-
      4      1.1      uch  * Copyright(c) 1996, 2001 The NetBSD Foundation, Inc.
      5      1.1      uch  * All rights reserved.
      6      1.1      uch  *
      7      1.1      uch  * This code is derived from software contributed to The NetBSD Foundation
      8      1.1      uch  * by Matthias Drochner. and UCHIYAMA Yasushi.
      9      1.1      uch  *
     10      1.1      uch  * Redistribution and use in source and binary forms, with or without
     11      1.1      uch  * modification, are permitted provided that the following conditions
     12      1.1      uch  * are met:
     13      1.1      uch  * 1. Redistributions of source code must retain the above copyright
     14      1.1      uch  *    notice, this list of conditions and the following disclaimer.
     15      1.1      uch  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1      uch  *    notice, this list of conditions and the following disclaimer in the
     17      1.1      uch  *    documentation and/or other materials provided with the distribution.
     18      1.1      uch  * 3. All advertising materials mentioning features or use of this software
     19      1.1      uch  *    must display the following acknowledgement:
     20      1.1      uch  *        This product includes software developed by the NetBSD
     21      1.1      uch  *        Foundation, Inc. and its contributors.
     22      1.1      uch  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23      1.1      uch  *    contributors may be used to endorse or promote products derived
     24      1.1      uch  *    from this software without specific prior written permission.
     25      1.1      uch  *
     26      1.1      uch  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27      1.1      uch  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28      1.1      uch  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29      1.1      uch  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30      1.1      uch  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31      1.1      uch  * CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32      1.1      uch  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33      1.1      uch  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34      1.1      uch  * CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE)
     35      1.1      uch  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36      1.1      uch  * POSSIBILITY OF SUCH DAMAGE.
     37      1.1      uch  */
     38      1.1      uch 
     39      1.1      uch #include <console.h>
     40      1.1      uch #include <file.h>
     41      1.1      uch 
     42      1.1      uch __BEGIN_DECLS
     43      1.1      uch #include <string.h>
     44      1.1      uch #include <zlib.h>
     45      1.1      uch __END_DECLS
     46      1.1      uch 
     47      1.1      uch static struct z_stream_s __stream;	// XXX for namespace.
     48      1.1      uch 
     49      1.1      uch void
     50      1.1      uch FileManager::_reset()
     51      1.1      uch {
     52      1.1      uch 	_stream = &__stream;
     53      1.1      uch 	memset(_stream, 0, sizeof(struct z_stream_s));
     54      1.1      uch 	_z_err = 0;
     55      1.1      uch 	_z_eof = 0;
     56      1.1      uch 	_crc = 0;
     57      1.1      uch 	_compressed = 0;
     58      1.1      uch }
     59      1.1      uch 
     60      1.1      uch FileManager::~FileManager()
     61      1.1      uch {
     62      1.1      uch 	delete _file;
     63      1.1      uch }
     64      1.1      uch 
     65      1.1      uch BOOL
     66      1.1      uch FileManager::setRoot(TCHAR *drive)
     67      1.1      uch {
     68      1.1      uch 	return _file->setRoot(drive);
     69      1.1      uch }
     70      1.1      uch 
     71      1.1      uch BOOL
     72      1.1      uch FileManager::open(const TCHAR *name, u_int32_t flags)
     73      1.1      uch {
     74      1.1      uch 	if (!_file->open(name, flags))
     75      1.1      uch 		return FALSE;
     76      1.1      uch 
     77      1.1      uch 	_reset();
     78      1.1      uch 
     79      1.1      uch 	if (inflateInit2(_stream, -15) != Z_OK)
     80      1.1      uch 		goto errout;
     81      1.1      uch 	_stream->next_in = _inbuf;
     82      1.1      uch 
     83      1.1      uch 	_check_header(); // skip the .gz header
     84      1.1      uch 
     85      1.1      uch 	return TRUE;
     86  1.1.4.1  nathanw  errout:
     87      1.1      uch 	_file->close();
     88      1.1      uch 	return FALSE;
     89      1.1      uch }
     90      1.1      uch 
     91      1.1      uch size_t
     92      1.1      uch FileManager::read(void *buf, size_t len, off_t ofs)
     93      1.1      uch {
     94      1.1      uch 	if (ofs != -1)
     95      1.1      uch 		seek(ofs);
     96      1.1      uch 
     97      1.1      uch 	return _read(buf, len);
     98      1.1      uch }
     99      1.1      uch 
    100      1.1      uch size_t
    101      1.1      uch FileManager::_read(void *buf, size_t len)
    102      1.1      uch {
    103      1.1      uch 	// starting point for crc computation
    104      1.1      uch 	u_int8_t *start = reinterpret_cast<u_int8_t *>(buf);
    105      1.1      uch 
    106      1.1      uch 	if (_z_err == Z_DATA_ERROR || _z_err == Z_ERRNO) {
    107      1.1      uch 		return -1;
    108      1.1      uch 	}
    109      1.1      uch 	if (_z_err == Z_STREAM_END) {
    110      1.1      uch 		return 0;  // EOF
    111      1.1      uch 	}
    112      1.1      uch 	_stream->next_out = reinterpret_cast<u_int8_t *>(buf);
    113      1.1      uch 	_stream->avail_out = len;
    114      1.1      uch 
    115      1.1      uch 	int got;
    116      1.1      uch 	while (_stream->avail_out != 0) {
    117      1.1      uch 		if (!_compressed) {
    118      1.1      uch 			// Copy first the lookahead bytes
    119      1.1      uch 			u_int32_t n = _stream->avail_in;
    120      1.1      uch 			if (n > _stream->avail_out)
    121      1.1      uch 				n = _stream->avail_out;
    122      1.1      uch 			if (n > 0) {
    123      1.1      uch 				memcpy(_stream->next_out, _stream->next_in, n);
    124      1.1      uch 				_stream->next_out  += n;
    125      1.1      uch 				_stream->next_in   += n;
    126      1.1      uch 				_stream->avail_out -= n;
    127      1.1      uch 				_stream->avail_in  -= n;
    128      1.1      uch 			}
    129      1.1      uch 			if (_stream->avail_out > 0) {
    130      1.1      uch 				got = _file->read(_stream->next_out,
    131  1.1.4.1  nathanw 				    _stream->avail_out);
    132      1.1      uch 				if (got == -1) {
    133      1.1      uch 					return(got);
    134      1.1      uch 				}
    135      1.1      uch 				_stream->avail_out -= got;
    136      1.1      uch 			}
    137      1.1      uch 			return(int)(len - _stream->avail_out);
    138      1.1      uch 		}
    139      1.1      uch 
    140      1.1      uch 		if (_stream->avail_in == 0 && !_z_eof) {
    141      1.1      uch 			got = _file->read(_inbuf, Z_BUFSIZE);
    142      1.1      uch 			if (got <= 0)
    143      1.1      uch 				_z_eof = 1;
    144      1.1      uch 
    145      1.1      uch 			_stream->avail_in = got;
    146      1.1      uch 			_stream->next_in = _inbuf;
    147      1.1      uch 		}
    148      1.1      uch 
    149      1.1      uch 		_z_err = inflate(_stream, Z_NO_FLUSH);
    150      1.1      uch 
    151      1.1      uch 		if (_z_err == Z_STREAM_END) {
    152      1.1      uch 			/* Check CRC and original size */
    153      1.1      uch 			_crc = crc32(_crc, start,(unsigned int)
    154  1.1.4.1  nathanw 			    (_stream->next_out - start));
    155      1.1      uch 			start = _stream->next_out;
    156      1.1      uch 
    157      1.1      uch 			if (_get_long() != _crc ||
    158      1.1      uch 			    _get_long() != _stream->total_out) {
    159      1.1      uch 
    160      1.1      uch 				_z_err = Z_DATA_ERROR;
    161      1.1      uch 			} else {
    162      1.1      uch 				/* Check for concatenated .gz files: */
    163      1.1      uch 				_check_header();
    164      1.1      uch 				if (_z_err == Z_OK) {
    165      1.1      uch 					inflateReset(_stream);
    166      1.1      uch 					_crc = crc32(0L, Z_NULL, 0);
    167      1.1      uch 				}
    168      1.1      uch 			}
    169      1.1      uch 		}
    170      1.1      uch 		if (_z_err != Z_OK || _z_eof)
    171      1.1      uch 			break;
    172      1.1      uch 	}
    173      1.1      uch 
    174      1.1      uch 	_crc = crc32(_crc, start,(unsigned int)(_stream->next_out - start));
    175      1.1      uch 
    176      1.1      uch 	return(int)(len - _stream->avail_out);
    177      1.1      uch }
    178      1.1      uch 
    179      1.1      uch size_t
    180      1.1      uch FileManager::write(const void *buf, size_t bytes, off_t ofs)
    181      1.1      uch {
    182      1.1      uch 	return _file->write(buf, bytes, ofs);
    183      1.1      uch }
    184      1.1      uch 
    185      1.1      uch size_t
    186      1.1      uch FileManager::size()
    187      1.1      uch {
    188      1.1      uch 	return _file->size();
    189      1.1      uch }
    190      1.1      uch 
    191      1.1      uch BOOL
    192      1.1      uch FileManager::close()
    193      1.1      uch {
    194      1.1      uch 	inflateEnd(_stream);
    195      1.1      uch 
    196      1.1      uch 	return _file->close();
    197      1.1      uch }
    198      1.1      uch 
    199      1.1      uch BOOL
    200      1.1      uch FileManager::seek(off_t offset)
    201      1.1      uch {
    202      1.1      uch 	if (!_compressed) {
    203      1.1      uch 		_file->seek(offset);
    204      1.1      uch 		_stream->avail_in = 0;
    205      1.1      uch 
    206      1.1      uch 		return TRUE;
    207      1.1      uch 	}
    208      1.1      uch 
    209      1.1      uch 	/* if seek backwards, simply start from the beginning */
    210      1.1      uch 	if (offset < _stream->total_out) {
    211      1.1      uch 		_file->seek(0);
    212      1.1      uch 
    213      1.1      uch 		inflateEnd(_stream);
    214      1.1      uch 		_reset(); /* this resets total_out to 0! */
    215      1.1      uch 		inflateInit2(_stream, -15);
    216      1.1      uch 		_stream->next_in = _inbuf;
    217      1.1      uch 
    218      1.1      uch 		_check_header(); /* skip the .gz header */
    219      1.1      uch 	}
    220      1.1      uch 
    221      1.1      uch 	/* to seek forwards, throw away data */
    222      1.1      uch 	if (offset > _stream->total_out) {
    223      1.1      uch 		off_t toskip = offset - _stream->total_out;
    224      1.1      uch 
    225      1.1      uch 		while (toskip > 0) {
    226      1.1      uch #define DUMMYBUFSIZE 256
    227      1.1      uch 			char dummybuf[DUMMYBUFSIZE];
    228      1.1      uch 			off_t len = toskip;
    229      1.1      uch 			if (len > DUMMYBUFSIZE)
    230      1.1      uch 				len = DUMMYBUFSIZE;
    231      1.1      uch 			if (_read(dummybuf, len) != len)
    232      1.1      uch 				return FALSE;
    233      1.1      uch 			toskip -= len;
    234      1.1      uch 		}
    235      1.1      uch 	}
    236      1.1      uch 
    237      1.1      uch 	return TRUE;
    238      1.1      uch }
    239      1.1      uch 
    240      1.1      uch //
    241      1.1      uch // GZIP util.
    242      1.1      uch //
    243      1.1      uch int
    244      1.1      uch FileManager::_get_byte()
    245      1.1      uch {
    246      1.1      uch 	if (_z_eof)
    247      1.1      uch 		return(EOF);
    248      1.1      uch 
    249      1.1      uch 	if (_stream->avail_in == 0) {
    250      1.1      uch 		int got;
    251      1.1      uch 
    252      1.1      uch 		got = _file->read(_inbuf, Z_BUFSIZE);
    253      1.1      uch 		if (got <= 0) {
    254      1.1      uch 			_z_eof = 1;
    255      1.1      uch 			return EOF;
    256      1.1      uch 		}
    257      1.1      uch 		_stream->avail_in = got;
    258      1.1      uch 		_stream->next_in = _inbuf;
    259      1.1      uch 	}
    260      1.1      uch 	_stream->avail_in--;
    261      1.1      uch 	return *(_stream->next_in)++;
    262      1.1      uch }
    263      1.1      uch 
    264      1.1      uch u_int32_t
    265      1.1      uch FileManager::_get_long()
    266      1.1      uch {
    267      1.1      uch 	u_int32_t x = static_cast<u_int32_t>(_get_byte());
    268      1.1      uch 	int c;
    269      1.1      uch 
    270      1.1      uch 	x +=(static_cast<u_int32_t>(_get_byte())) << 8;
    271      1.1      uch 	x +=(static_cast<u_int32_t>(_get_byte())) << 16;
    272      1.1      uch 	c = _get_byte();
    273      1.1      uch 	if (c == EOF)
    274      1.1      uch 		_z_err = Z_DATA_ERROR;
    275      1.1      uch 	x +=(static_cast<u_int32_t>(c)) << 24;
    276      1.1      uch 
    277      1.1      uch 	return x;
    278      1.1      uch }
    279      1.1      uch 
    280      1.1      uch void
    281      1.1      uch FileManager::_check_header()
    282      1.1      uch {
    283      1.1      uch 	int method; /* method byte */
    284      1.1      uch 	int flags;  /* flags byte */
    285      1.1      uch 	unsigned int len;
    286      1.1      uch 	int c;
    287      1.1      uch 
    288      1.1      uch 	/* Check the gzip magic header */
    289      1.1      uch 	for (len = 0; len < 2; len++) {
    290      1.1      uch 		c = _get_byte();
    291      1.1      uch 		if (c == _gz_magic[len])
    292      1.1      uch 			continue;
    293      1.1      uch 		if ((c == EOF) &&(len == 0))  {
    294      1.1      uch 			/*
    295      1.1      uch 			 * We must not change _compressed if we are at EOF;
    296      1.1      uch 			 * we may have come to the end of a gzipped file and be
    297      1.1      uch 			 * check to see if another gzipped file is concatenated
    298      1.1      uch 			 * to this one. If one isn't, we still need to be able
    299      1.1      uch 			 * to lseek on this file as a compressed file.
    300      1.1      uch 			 */
    301      1.1      uch 			return;
    302      1.1      uch 		}
    303      1.1      uch 		_compressed = 0;
    304      1.1      uch 		if (c != EOF) {
    305      1.1      uch 			_stream->avail_in++;
    306      1.1      uch 			_stream->next_in--;
    307      1.1      uch 		}
    308      1.1      uch 		_z_err = _stream->avail_in != 0 ? Z_OK : Z_STREAM_END;
    309      1.1      uch 		return;
    310      1.1      uch 	}
    311      1.1      uch 	_compressed = 1;
    312      1.1      uch 	method = _get_byte();
    313      1.1      uch 	flags = _get_byte();
    314      1.1      uch 	if (method != Z_DEFLATED ||(flags & RESERVED) != 0) {
    315      1.1      uch 		_z_err = Z_DATA_ERROR;
    316      1.1      uch 		return;
    317      1.1      uch 	}
    318      1.1      uch 
    319      1.1      uch 	/* Discard time, xflags and OS code: */
    320      1.1      uch 	for (len = 0; len < 6; len++)
    321      1.1      uch 		(void)_get_byte();
    322      1.1      uch 
    323      1.1      uch 	if ((flags & EXTRA_FIELD) != 0) {
    324      1.1      uch 		/* skip the extra field */
    325      1.1      uch 		len  = (unsigned int)_get_byte();
    326      1.1      uch 		len +=((unsigned int)_get_byte()) << 8;
    327      1.1      uch 		/* len is garbage if EOF but the loop below will quit anyway */
    328      1.1      uch 		while (len-- != 0 && _get_byte() != EOF) /*void*/;
    329      1.1      uch 	}
    330      1.1      uch 	if ((flags & ORIG_NAME) != 0) {
    331      1.1      uch 		/* skip the original file name */
    332      1.1      uch 		while ((c = _get_byte()) != 0 && c != EOF) /*void*/;
    333      1.1      uch 	}
    334      1.1      uch 	if ((flags & COMMENT) != 0) {
    335      1.1      uch 		/* skip the .gz file comment */
    336      1.1      uch 		while ((c = _get_byte()) != 0 && c != EOF) /*void*/;
    337      1.1      uch 	}
    338      1.1      uch 	if ((flags & HEAD_CRC) != 0) {  /* skip the header crc */
    339      1.1      uch 		for (len = 0; len < 2; len++)
    340      1.1      uch 			(void)_get_byte();
    341      1.1      uch 	}
    342      1.1      uch 	_z_err = _z_eof ? Z_DATA_ERROR : Z_OK;
    343      1.1      uch }
    344