⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compressed.c

📁 linux下自动mount各种即插即用设备的一个小程序源码 文件包含内容: /vold.h /vold.c /split.h /split.c /disktype-6/disktype.c
💻 C
字号:
/* * compressed.c * Layered data source for compressed files. * * Copyright (c) 2003 Christoph Pfisterer * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE.  */#include "detect.h"#include <signal.h>#include <sys/wait.h>#define DEBUG 0#ifndef FD_ZERO#define DECOMPRESS 0#warning Transparent decompression disabled, select() macros not defined#else#define DECOMPRESS 1#endif/* * types */#if DECOMPRESStypedef struct compressed_source {	SOURCE c;	U64 offset, write_pos, write_max;	int write_pipe, read_pipe, nfds;	pid_t pid;}COMPRESSED_SOURCE;#endif/* * helper functions */static void handle_compressed(SECTION *section, int level,                              int off, const char *program);#if DECOMPRESSstatic SOURCE *init_compressed_source(SOURCE *foundation, U64 offset, U64 size,                                      const char *program);static U64 read_compressed(SOURCE *s, U64 pos, U64 len, void *buf);static void close_compressed(SOURCE *s);#endif/* * compressed file detection */void detect_compressed(SECTION *section, int level) {	int fill, off, sector;	unsigned char *buf;	fill = get_buffer(section, 0, 4096, (void **)&buf);	/* look for signatures at sector beginnings */	for (off = 0; off + 512 <= fill; off += 512) {		sector = off >> 9;		/* compress */		if (buf[off] == 037 && buf[off+1] == 0235) {			if (sector > 0)				print_line(level, "compress-compressed data at sector %d", sector);			else				print_line(level, "compress-compressed data");			handle_compressed(section, level, off, "gzip");			break;		}		/* gzip */		if (buf[off] == 037 && (buf[off+1] == 0213 || buf[off+1] == 0236)) {			if (sector > 0)				print_line(level, "gzip-compressed data at sector %d", sector);			else				print_line(level, "gzip-compressed data");			handle_compressed(section, level, off, "gzip");			break;		}		/* bzip2 */		if (memcmp(buf + off, "BZh", 3) == 0) {			if (sector > 0)				print_line(level, "bzip2-compressed data at sector %d", sector);			else				print_line(level, "bzip2-compressed data");			handle_compressed(section, level, off, "bzip2");			break;		}	}}static void handle_compressed(SECTION *section, int level,                              int off, const char *program) {#if DECOMPRESS	SOURCE *s;	U64 size;	/* create decompression data source */	size = section->size;	if (size > 0)		size -= off;	s = init_compressed_source(section->source,	                           section->pos + off, size, program);	analyze_source(s, level + 1);	close_source(s);#else	print_line(level + 1, "Decompression disabled on this system");#endif}/* * initialize the decompression */#if DECOMPRESSstatic SOURCE *init_compressed_source(SOURCE *foundation, U64 offset, U64 size,                                      const char *program) {	COMPRESSED_SOURCE *cs;	int write_pipe[2], read_pipe[2], flags;	cs = (COMPRESSED_SOURCE *)malloc(sizeof(COMPRESSED_SOURCE));	if (cs == NULL)		bailout("Out of memory");	memset(cs, 0, sizeof(COMPRESSED_SOURCE));	cs->c.sequential = 1;	cs->c.seq_pos = 0;	cs->c.foundation = foundation;	cs->c.read_bytes = read_compressed;	cs->c.close = close_compressed;	/* size is not known in advance by definition */	cs->offset = offset;	cs->write_pos = 0;	cs->write_max = size;	/* open "gzip -dc" in a dual pipe */	if (pipe(write_pipe) < 0)		bailoute("pipe for decompression");	if (pipe(read_pipe) < 0)		bailoute("pipe for decompression");	cs->write_pipe = write_pipe[1];	cs->read_pipe = read_pipe[0];	cs->pid = fork();	if (cs->pid < 0) {		bailoute("fork");	}	if (cs->pid == 0) {  /* we're the child process */		/* set up pipe */		dup2(write_pipe[0], 0);		if (write_pipe[0] > 2)			close(write_pipe[0]);		close(write_pipe[1]);		close(read_pipe[0]);		dup2(read_pipe[1], 1);		if (read_pipe[1] > 2)			close(read_pipe[1]);		/* execute decompressor (gzip or bzip2) */		execlp(program, program, "-dc", NULL);		exit(0);	}	/* we're the parent process */	close(write_pipe[0]);	close(read_pipe[1]);	/* set non-blocking I/O */	if ((flags = fcntl(cs->write_pipe, F_GETFL, 0)) >= 0)		fcntl(cs->write_pipe, F_SETFL, flags | O_NONBLOCK);	else		bailoute("set pipe flags");	if ((flags = fcntl(cs->read_pipe, F_GETFL, 0)) >= 0)		fcntl(cs->read_pipe, F_SETFL, flags | O_NONBLOCK);	else		bailoute("set pipe flags");	cs->nfds = ((cs->read_pipe > cs->write_pipe) ?	            cs->read_pipe : cs->write_pipe) + 1;	return (SOURCE *)cs;}/* * raw read */static U64 read_compressed(SOURCE *s, U64 pos, U64 len, void *buf) {	COMPRESSED_SOURCE *cs = (COMPRESSED_SOURCE *)s;	SOURCE *fs = s->foundation;	char *p, *filebuf;	U64 got, fill;	int askfor, selresult;	ssize_t result;	fd_set read_set;	fd_set write_set;#if DEBUG	printf("rc got asked for pos %llu len %llu\n", pos, len);#endif	p = (char *)buf;	got = 0;	if (cs->read_pipe < 0)  /* closed for reading */		return got;	while (got < len) {		result = read(cs->read_pipe, p, len - got);#if DEBUG		printf("rc read got %d\n", result);#endif		if (result == 0) {  /* end of file */			/* remember size for buffer layer */			s->size_known = 1;			s->size = s->seq_pos + got;			/* close pipe (stops future read attempts in the track) */			close(cs->read_pipe);			cs->read_pipe = -1;			/* we're done */			break;		} else if (result > 0) {  /* got data */			p += result;			got += result;			continue;		} else {  /* error return */			if (errno == EINTR)				continue;			if (errno != EAGAIN) {				errore("read from pipe");				break;			}		}		/* no data available for reading right now, so try to write		   some uncompressed data down the other pipe for a change */		/* calculate how much data to write */		askfor = 4096;		if (cs->write_max && cs->write_pos + askfor > cs->write_max)			askfor = cs->write_max - cs->write_pos;		if (askfor <= 0 && cs->write_pipe >= 0) {			/* there's no more data to write, close the pipe */			close(cs->write_pipe);			cs->write_pipe = -1;		}		if (cs->write_pipe < 0) {			/* no more data to write, just wait for input using select */			FD_ZERO(&read_set);			FD_SET(cs->read_pipe, &read_set);#if DEBUG			printf("rc starting select\n");#endif			selresult = select(cs->nfds, &read_set, NULL, NULL, NULL);#if DEBUG			printf("rc select got %d\n", selresult);#endif			if (selresult < 0 && errno != EINTR) {				errore("select");				break;			}			continue;		}		/* get data from lower layer */		fill = get_buffer_real(fs, cs->offset + cs->write_pos, askfor,		                       NULL, (void **)&filebuf);#if DEBUG		printf("rc get_buffer asked for pos %llu len %d got %llu\n",		       cs->offset + cs->write_pos, askfor, fill);#endif		if (fill < askfor) {			/* we reached the end of compressed input, note that down */			cs->write_max = cs->write_pos + fill;		}		if (fill <= 0) {			/* didn't get any data to write, so no need trying */			/* NOTE: in this case, the above if() also caught on and the next			time through the loop, the write pipe will be closed. */			continue;		}		/* try a write right now */		result = write(cs->write_pipe, filebuf, fill);#if DEBUG		printf("rc write got %d\n", result);#endif		if (result >= 0) {			cs->write_pos += result;			continue;  /* see if that made more data available for reading */		} else {			if (errno == EINTR)				continue;			if (errno != EAGAIN) {				errore("write to pipe");				break;			}		}		/* both pipes are blocked right now. wait using select(). */		FD_ZERO(&read_set);		FD_ZERO(&write_set);		FD_SET(cs->read_pipe, &read_set);		FD_SET(cs->write_pipe, &write_set);#if DEBUG		printf("rc starting select\n");#endif		selresult = select(cs->nfds, &read_set, &write_set, NULL, NULL);#if DEBUG		printf("rc select got %d\n", selresult);#endif		if (selresult < 0 && errno != EINTR) {			errore("select");			break;		}	}	return got;}/* * close cleanup */static void close_compressed(SOURCE *s) {	COMPRESSED_SOURCE *cs = (COMPRESSED_SOURCE *)s;	int status;	if (cs->write_pipe >= 0)		close(cs->write_pipe);	if (cs->read_pipe >= 0)		close(cs->read_pipe);	kill(cs->pid, SIGHUP);	waitpid(cs->pid, &status, 0);}#endif /* DECOMPRESS *//* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -