compress.c revision a77d64af7813dad3dad148a9974e0ec7b80d1f43
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1986 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Compress - data compression program
*/
#define min(a, b) ((a > b) ? b : a)
/*
* machine variants which require cc -Dmachine: pdp11, z8000, pcxt
*/
/*
* Set USERMEM to the maximum amount of physical user memory available
* in bytes. USERMEM is used to determine the maximum BITS that can be used
* for compression.
*
* SACREDMEM is the amount of physical memory saved for others; compress
* will hog the rest.
*/
#ifndef SACREDMEM
#define SACREDMEM 0
#endif
#ifndef USERMEM
#endif
#ifdef USERMEM
#define PBITS 16
#else
#define PBITS 15
#else
#define PBITS 14
#else
#define PBITS 13
#else
#define PBITS 12
#endif
#endif
#endif
#endif
#endif /* USERMEM */
#ifdef PBITS /* Preferred BITS for this memory size */
#ifndef BITS
#endif /* BITS */
#endif /* PBITS */
#if BITS == 16
#endif
#if BITS == 15
#endif
#if BITS == 14
#endif
#if BITS == 13
#endif
#if BITS <= 12
#endif
/*
* a code_int must be able to hold 2**BITS values of type int, and also -1
*/
#if BITS > 15
typedef long int code_int;
#else
typedef int code_int;
#endif
typedef long int count_int;
typedef long long count_long;
typedef unsigned char char_type;
/* Defines for third byte of header */
#define BIT_MASK 0x1f
#define BLOCK_MASK 0x80
/*
* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is
* a fourth header byte(for expansion).
*/
/*
* compress.c - File compression ala IEEE Computer, June 1984.
*/
static char rcs_ident[] =
"$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $";
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h> /* XCU4 */
#include <limits.h>
#include <libintl.h>
#include <locale.h>
#include <langinfo.h>
#include <string.h>
#include <utime.h>
#include <libgen.h>
#include <setjmp.h>
#include <strings.h>
#include <fcntl.h>
#include <dirent.h>
/*
* Multi-byte handling for 'y' or 'n'
*/
static char *yesstr; /* string contains int'l for "yes" */
static char *nostr; /* string contains int'l for "yes" */
static int ynsize = 0; /* # of (multi)bytes for "y" */
static char *yesorno; /* int'l input for 'y' */
/* should NEVER generate this code */
static unsigned short codetab [OUTSTACKSIZE];
/*
* To save much memory, we overlay the table used by compress() with those
* used by decompress(). The tab_prefix table is the same size and type
* as the codetab. The tab_suffix table needs 2**BITS characters. We
* get this from the beginning of htab. The output stack uses the rest
* of htab, and contains characters. There is plenty of room for any
* possible stack (stack used to be 8000 characters).
*/
#define tab_prefixof(i) codetabof(i)
static int newline_needed = 0;
static int didnt_shrink = 0;
static int perm_stat = 0; /* permanent status */
/* Use a 3-byte magic number header, unless old file */
static int nomagic = 0;
/* Write output on stdout, suppress messages */
static int zcat_flg = 0; /* use stdout on all files */
static int zcat_cmd = 0; /* zcat cmd */
static int use_stdout = 0; /* set for each file processed */
/* Don't unlink output file on interrupt */
static int precious = 1;
/*
* block compression parameters -- after all codes are used up,
* and compression rate changes, start over.
*/
static int block_compress = BLOCK_MASK;
static int clear_flg = 0;
static long int ratio = 0;
/*
* the next two codes should not be changed lightly, as they must not
* lie within the contiguous general code space.
*/
static int force = 0;
static char ofname [MAXPATHLEN];
static int Vflg = 0;
static int vflg = 0;
static int qflg = 0;
static int bflg = 0;
static int Fflg = 0;
static int dflg = 0;
static int cflg = 0;
static int Cflg = 0;
#ifdef DEBUG
int verbose = 0;
int debug = 0;
#endif /* DEBUG */
static void (*oldint)();
static int bgnd_flag;
static int do_decomp = 0;
static char *progname;
static char *optstr;
/*
* Fix lint errors
*/
static char *local_basename(char *);
static void Usage(void);
static void cl_block(count_long);
static void compress(void);
static void decompress(void);
static void ioerror(void);
static void onintr();
static void oops();
static void version(void);
static int mv_xattrs(char *, char *, int);
#ifdef DEBUG
static int in_stack(int, int);
static void dump_tab(void);
static void printcodes(void);
#endif
/* For error-handling */
/* For input and ouput */
/* For output() */
{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
/* For compress () */
static int offset;
/* # of codes output (for debugging) */
/* For dump_tab() */
#define STACK_SIZE 15000
#ifdef DEBUG
#endif
/*
* *************************************************************
* TAG( main )
*
* Algorithm from "A Technique for High Performance Data Compression",
* Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19.
*
* Usage: compress [-dfvc] [-b bits] [file ...]
* Inputs:
* -d: If given, decompression is done instead.
*
* -c: Write output on stdout, don't remove original.
*
*
* -f: Forces output file to be generated, even if one already
* exists, and even if no space is saved by compressing.
* If -f is not used, the user will be prompted if stdin is
* a tty, otherwise, the output file will not be overwritten.
*
* -v: Write compression statistics
*
* file ...: Files to be compressed. If none specified, stdin
* is used.
* Outputs:
* file.Z: Compressed form of file with same mode, owner, and utimes
* or stdout (if stdin used as input)
*
* Assumptions:
* When filenames are given, replaces with the compressed version
* (.Z suffix) only if the file decreases in size.
* Algorithm:
* Modified Lempel-Ziv method (LZW). Basically finds common
* substrings and replaces them with a variable size code. This is
* deterministic, and can be done on the fly. Thus, the decompression
* procedure needs no input table, but tracks the way the table was built.
*/
int
{
int overwrite = 0; /* Do not overwrite unless given -f flag */
char tempname[MAXPATHLEN];
char *cp;
int ch; /* XCU4 */
extern char *optarg;
int dash_count = 0; /* times "-" is on cmdline */
/* XCU4 changes */
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
/* Build multi-byte char for 'y' char */
yptr = "y";
/* Build multi-byte char for 'n' char */
nptr = "n";
/* Build multi-byte char for input char */
/* This bg check only works for sh. */
}
/* Allocate room for argv + "-" (if stdin needs to be added) */
cp++;
} else {
}
do_decomp = 1;
do_decomp = 1;
}
/*
* Argument Processing
* All flags are optional.
* -D = > debug
* -V = > print Version; debug verbose
* -d = > do_decomp
* -v = > unquiet
* -f = > force overwrite of output file
* -n = > no header: useful to uncompress old files
* -b maxbits => maxbits. If -b is specified,
* then maxbits MUST be given also.
* -c = > cat all output to stdout
* -C = > generate output compatible with compress 2.0.
* if a string is left, must be an input filename.
*/
#ifdef DEBUG
optstr = "b:cCdDfFnqvV";
#else
optstr = "b:cCdfFnqvV";
#endif
/* Process all flags in this arg */
switch (ch) {
#ifdef DEBUG
case 'D':
debug = 1;
break;
case 'V':
verbose = 1;
version();
break;
#else
case 'V':
version();
Vflg++;
break;
#endif /* DEBUG */
case 'v':
quiet = 0;
vflg++;
break;
case 'd':
do_decomp = 1;
dflg++;
break;
case 'f':
case 'F':
Fflg++;
overwrite = 1;
force = 1;
break;
case 'n':
nomagic = 1;
break;
case 'C':
Cflg++;
block_compress = 0;
break;
case 'b':
bflg++;
p = optarg;
if (!p) {
"Missing maxbits\n"));
Usage();
exit(1);
}
if (*p) {
"Missing maxbits\n"));
Usage();
exit(1);
}
break;
case 'c':
cflg++;
zcat_flg = 1;
break;
case 'q':
qflg++;
quiet = 1;
break;
default:
"Unknown flag: '%c'\n"), optopt);
Usage();
exit(1);
}
} /* while */
/*
* Validate zcat syntax
*/
"Invalid Option\n"));
Usage();
exit(1);
}
/*
* Process the file list
*/
dash_count++;
}
}
if (dash_count > 1) {
gettext("%s may only appear once in the file"
" list\n"), "\"-\"");
exit(1);
}
*fileptr++ = "-";
}
gettext("compress: only one file may be compressed"
" to stdout\n"));
exit(1);
}
/* Need to open something to close with freopen later */
"input\n"));
exit(1);
}
"output\n"));
exit(1);
}
int jmpval = 0;
didnt_shrink = 0;
newline_needed = 0;
if (do_decomp) {
/* DECOMPRESSION */
/* process stdin */
use_stdout = 1;
} else {
/* process the named file */
use_stdout = 0;
if (zcat_flg) {
use_stdout = 1;
}
/* Check for .Z suffix */
/* No .Z: tack one on */
sizeof (tempname)) >=
sizeof (tempname)) {
gettext("%s: filename "
"too long\n"),
*fileptr);
perm_stat = 1;
continue;
}
sizeof (tempname)) < 0) {
perm_stat = 1;
continue;
}
}
/* Open input file */
perm_stat = 1;
continue;
}
perm_stat = 1;
continue;
}
}
/* Check the magic number */
if (nomagic == 0) {
(magic_header[0] & 0xFF)) ||
"%s: not in compressed "
"format\n"),
*fileptr);
perm_stat = 1;
continue;
}
/* set -b from file */
perm_stat = 1;
continue;
}
gettext("%s: compressed "
"with %d bits, "
"can only handle"
" %d bits\n"),
perm_stat = 1;
continue;
}
}
if (!use_stdout) {
/* Generate output filename */
sizeof (ofname)) >=
sizeof (ofname)) {
gettext("%s: filename "
"too long\n"),
*fileptr);
perm_stat = 1;
continue;
}
/* Strip off .Z */
}
} else {
/* COMPRESSION */
/* process stdin */
use_stdout = 1;
/* Use the largest possible hash table */
} else {
/* process the named file */
use_stdout = 0;
if (zcat_flg) {
use_stdout = 1;
}
"%s: already has .Z "
"suffix -- no change\n"),
*fileptr);
perm_stat = 1;
continue;
}
/* Open input file */
perm_stat = 1;
continue;
}
perm_stat = 1;
continue;
}
/*
* tune hash table size for small
* files -- ad hoc,
* but the sizes match earlier #defines, which
* serve as upper bounds on the number of
* output codes.
*/
else if (fsize < 47000)
if (!use_stdout) {
/* Generate output filename */
sizeof (ofname)) >=
sizeof (ofname)) {
gettext("%s: filename "
"too long\n"),
*fileptr);
perm_stat = 1;
continue;
}
sizeof (ofname)) < 0) {
perm_stat = 1;
continue;
}
}
}
} /* if (do_decomp) */
/* Check for overwrite of existing file */
if (!overwrite && !use_stdout) {
"%s already exists;"), ofname);
int cin;
" do you wish to overwr"
"ite %s (%s or %s)? "),
cin++)
ynsize);
ynsize) == 0) ||
(yesorno[0] == 'y') ||
(yesorno[0] == 'Y'))) {
"\tnot overwri"
"tten\n"));
continue;
}
} else {
/*
* XPG4: Assertion 1009
* Standard input is not
* terminal, and no '-f',
* and file exists.
*/
"%s: File exists, -f not"
" specified, and ru"
"nning in the backgro"
"und.\n"), *fileptr);
perm_stat = 1;
continue;
}
}
}
if (!use_stdout) {
}
/* Open output file */
perm_stat = 1;
continue;
}
precious = 0;
if (!quiet) {
*fileptr);
newline_needed = 1;
}
*fileptr);
newline_needed = 1;
}
/* Actually do the compression/decompression */
/* We'll see how things go */
#ifndef DEBUG
if (do_decomp == 0) {
compress();
} else {
decompress();
}
#else
if (do_decomp == 0) {
compress();
} else if (debug == 0) {
decompress();
} else {
printcodes();
}
if (verbose) {
dump_tab();
}
#endif
} else {
/*
* Things went badly - clean up and go on.
* jmpval's values break down as follows:
* 1 == message determined by ferror() values.
* 2 == input problem message needed.
* 3 == output problem message needed.
*/
if (do_decomp) {
"uncompress: %s: corrupt"
" input\n"), *fileptr);
} else {
}
}
/* handle output errors */
if (use_stdout) {
perror("");
} else {
}
}
if (ofname[0] != '\0') {
}
ofname[0] = '\0';
}
perm_stat = 1;
continue;
}
/* Things went well */
if (!use_stdout) {
/* Copy stats */
precious = 1;
if (newline_needed) {
}
/*
* Print the info. for unchanged file
* when no -v
*/
if (didnt_shrink) {
if (quiet) {
"%s: -- file "
"unchanged\n"),
*fileptr);
}
perm_stat = 2;
}
}
} else {
perm_stat = 2;
}
if (newline_needed) {
}
}
} /* for */
return (perm_stat);
}
static void
{
/* we have exceeded the hash table */
"internal error: hashtable exceeded - hsize = %ld\n", hsize);
}
static code_int
{
while (i < 0) {
i += hsize_reg;
}
while (i >= hsize_reg) {
i -= hsize_reg;
}
return (i);
}
/*
* compress inp to outp
*
* Algorithm: use open addressing double hashing(no chaining) on the
* prefix code / next character combination. We do a variant of Knuth's
* algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
* secondary probe. Here, the modular division first probe is gives way
* to a faster exclusive-or manipulation. Also do block compression with
* an adaptive reset, whereby the code table is cleared when the compression
* ratio decreases, but after the table fills. The variable-length output
* codes are re-sized at this point, and a special CLEAR code is generated
* for the decompressor. Late addition: construct the table according to
* file size for noticeable speed improvement on small files. Please direct
* questions about this implementation to ames!jaw.
*/
static void
compress()
{
long fcode;
code_int i = 0;
int c;
int disp;
int hshift;
int probecnt;
int maxbits_reg;
#ifdef DEBUG
count_long out_count = 0;
#endif
if (nomagic == 0) {
ioerror();
}
}
offset = 0;
clear_flg = 0;
ratio = 0;
in_count = 1;
inchi = 0;
inclo = 1;
ioerror();
}
hshift = 0;
hshift++;
if (++inclo == 0)
inchi++;
if ((unsigned int)i >= hsize_reg)
continue;
} else if ((long)htabof(i) < 0) {
/* empty slot */
goto nomatch;
}
/* secondary hash (after G. Knott) */
if (i == 0) {
disp = 1;
}
probecnt = 0;
if ((i -= disp) < 0) {
while (i < 0)
i += hsize_reg;
}
continue;
}
if ((long)htabof(i) > 0) {
goto probe;
}
#ifdef DEBUG
out_count++;
#endif
ent = c;
if (free_ent < maxmaxcode) {
/* code -> hashtable */
} else {
if ((count_long)in_count >=
}
}
}
ioerror();
}
/*
* Put out the final code.
*/
#ifdef DEBUG
out_count++;
#endif
/*
* Print out stats on stderr
*/
if (!quiet) {
#ifdef DEBUG
"%lld chars in, %lld codes (%lld bytes) out, "
"compression factor: ",
(count_long) bytes_out);
"\tLargest code (of last block) was %d"
" (%d bits)\n",
#else /* !DEBUG */
#endif /* DEBUG */
}
/* report if no savings */
didnt_shrink = 1;
}
}
/*
* **************************************************************
* TAG(output)
*
* Output the given code.
* Inputs:
* code: A n_bits-bit integer. If == -1, then EOF. This assumes
* that n_bits = < (long)wordsize - 1.
* Outputs:
* Outputs code to the file.
* Assumptions:
* Chars are 8 bits long.
* Algorithm:
* Maintain a BITS character long buffer(so that 8 codes will
* fit in it exactly). Use the VAX insv instruction to insert each
* code in turn. When the buffer fills up empty it and start over.
*/
static void
{
#ifdef DEBUG
static int col = 0;
#endif /* DEBUG */
#ifdef DEBUG
if (verbose)
#endif /* DEBUG */
if (code >= 0) {
/*
* by the following code
*/
/*
* Get to the first byte.
*/
r_off &= 7;
/*
* Since code is always >= 8 bits, only need to mask the first
* hunk on the left.
*/
bp++;
/*
* Get any 8 bit parts in the middle (<=1 for up to 16
* bits).
*/
if (bits >= 8) {
code >>= 8;
bits -= 8;
}
/* Last bits. */
if (bits)
do {
ioerror();
}
bp++;
} while (--bits);
offset = 0;
}
/*
* If the next entry is going to be too big for the code size,
* then increase it, if possible.
*/
/*
* Write the whole buffer, because the input
* side won't discover the size increase until
* after it has read it.
*/
if (offset > 0) {
}
}
offset = 0;
if (clear_flg) {
clear_flg = 0;
} else {
n_bits++;
else
}
#ifdef DEBUG
if (debug) {
"\nChange to %d bits\n", n_bits);
col = 0;
}
#endif /* DEBUG */
}
} else {
/*
* At EOF, write the rest of the buffer.
*/
if (offset > 0) {
ioerror();
}
}
offset = 0;
#ifdef DEBUG
if (verbose)
#endif /* DEBUG */
ioerror();
}
}
/*
* Decompress inp to outp. This routine adapts to the codes in the
* file building the "string" table on-the-fly; requiring no table to
* be stored in the compressed file. The tables used herein are shared
* with those of the compress() routine. See the definitions above.
*/
static void
{
int finchar;
/*
* As above, initialize the first 256 entries in the table.
*/
tab_prefixof(code) = 0;
}
return; /* Get out of here */
/* first code must be 8 bits = char */
/* Crash if can't write */
ioerror();
}
tab_prefixof(code) = 0;
clear_flg = 1;
break;
}
/*
* Special case for KwKwK string.
*/
} else {
/* badness */
}
}
/*
* Generate output characters in reverse order
*/
while (code >= 256) {
} else {
/* badness */
}
}
/*
* And put them out in forward order
*/
do {
stackp--;
ioerror();
/*
* Generate the new entry.
*/
}
/*
* Remember previous code.
*/
}
ioerror();
}
/*
* **************************************************************
* TAG( getcode )
*
* Read one code from the standard input. If EOF, return -1.
* Inputs:
* inp
* Outputs:
* code or -1 is returned.
*/
getcode() {
/*
* If the next entry will be too big for the current code
* size, then we must increase the size. This implies reading
* a new buffer full, too.
*/
n_bits++;
/* won't get any bigger now */
else
}
if (clear_flg > 0) {
clear_flg = 0;
}
if (size <= 0) {
/* end of file */
return (-1);
ioerror();
}
}
offset = 0;
/* Round size down to integral number of codes */
}
/*
* Get to the first byte.
*/
r_off &= 7;
/* Get first part (low order bits) */
/* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
if (bits >= 8) {
r_off += 8;
bits -= 8;
}
/* high order bits. */
return (code);
}
#ifdef DEBUG
static void
{
/*
* Just print out codes from input file. For debugging.
*/
clear_flg = 1;
} else if (free_ent < maxmaxcode)
free_ent++;
col = 0;
}
}
}
#endif /* DEBUG */
#ifdef DEBUG
static void
dump_tab() /* dump string table */
{
int i, first;
int ent;
int stack_top = STACK_SIZE;
int c;
if (do_decomp == 0) { /* compressing */
int flag = 1;
for (i = 0; i < hsize; i++) { /* build sort pointers */
if ((long)htabof(i) >= 0) {
}
}
ent > 256;
}
}
} else if (!debug) { /* decompressing */
for (i = 0; i < free_ent; i++) {
ent = i;
c = tab_suffixof(ent);
else
NULL)) {
}
}
}
}
#endif /* DEBUG */
#ifdef DEBUG
static int
{
} else {
switch (c) {
default:
break;
}
}
return (stack_top);
}
#endif /* DEBUG */
static void
ioerror()
{
}
static void
{
int aclcnt;
if (!quiet) {
newline_needed = 1;
}
perm_stat = 1;
return;
if (quiet) {
}
" -- not a regular file: unchanged"));
newline_needed = 1;
perm_stat = 1;
if (quiet) {
}
" -- has %d other links: unchanged"),
newline_needed = 1;
perm_stat = 1;
} else if (didnt_shrink && !force) {
/* No compression: remove file.Z */
if (!quiet) {
" -- file unchanged"));
newline_needed = 1;
}
"%s: -- cannot preserve extended attributes, "
"file unchanged"), ifname);
newline_needed = 1;
/* Move attributes back ... */
perm_stat = 1;
} else { /* ***** Successful Compression ***** */
/* Copy ACL info */
"%s: failed to get acl count\n"),
ifname);
perm_stat = 1;
}
/*
* Get ACL info: don't bother allocating space if
* there are only standard permissions, i.e.,
* ACL count < 4.
*/
if (aclcnt > MIN_ACL_ENTRIES) {
"Insufficient memory\n"));
exit(1);
}
"%s: failed to get acl entries\n"),
ifname);
perm_stat = 1;
} else {
"%s: failed to set acl "
"entries\n"), ofname);
perm_stat = 1;
}
}
}
/* Copy ownership */
/* Update last accessed and modified times */
if (!quiet) {
" -- replaced with %s"), ofname);
newline_needed = 1;
}
return; /* Successful return */
}
/* Unsuccessful return -- one of the tests failed */
if (ofname[0] != '\0') {
}
ofname[0] = '\0';
}
}
static void
onintr()
{
exit(1);
}
static void
oops() /* wild pointer -- assume bad input */
{
if (do_decomp) {
}
}
exit(1);
}
static void
{
#ifdef DEBUG
if (debug) {
}
#endif /* DEBUG */
/* shift will overflow */
if (rat == 0) { /* Don't divide by zero */
rat = 0x7fffffffffffffffLL;
} else {
}
} else {
/* 8 fractional bits */
}
} else {
ratio = 0;
#ifdef DEBUG
if (verbose)
dump_tab(); /* dump string table */
#endif
clear_flg = 1;
#ifdef DEBUG
if (debug)
#endif /* DEBUG */
}
}
static void
{
long i;
long m1 = -1;
i = hsize - 16;
do { /* might use Sys V memset(3) here */
htab_p -= 16;
} while ((i -= 16) >= 0);
for (i += 16; i > 0; i--)
}
static void
{
int q; /* store percentage */
if (q < 0) {
q = -q;
}
}
static void
version()
{
#ifdef DEBUG
#endif
}
static void
Usage()
{
#ifdef DEBUG
"Usage: compress [-dDVfc] [-b maxbits] [file ...]\n");
#else
"Usage: compress [-fv] [-b maxbits] [file ...]\n"\
" compress [-cfv] [-b maxbits] [file]\n"));
"Usage: uncompress [-cfv] [file ...]\n"));
#endif /* DEBUG */
}
static char *
local_basename(char *path)
{
char *p;
ret = p + 1;
return (ret);
}
static int
{
char *fn_dup;
char *dir;
long int max_name;
long int max_path;
/* Check for component length too long */
gettext("%s: filename too long to tack on .Z:"
return (-1);
}
/* Check for path length too long */
gettext("%s: Pathname too long to tack on .Z:"
return (-1);
}
gettext("%s: Buffer overflow adding .Z to %s\n"),
return (-1);
}
return (0);
}
/*
* mv_xattrs - move (via renameat) all of the extended attributes
* associated with the file infile to the file outfile.
* This function returns 0 on success and -1 on error.
*/
static int
{
int error = 0;
char *etext;
error = -1;
goto out;
}
error = -1;
goto out;
}
error = -1;
goto out;
}
error = -1;
goto out;
}
continue;
error = -1;
goto out;
}
}
out:
if (quiet) {
} else {
}
}
if (dirp)
if (indfd != -1)
if (outdfd != -1)
return (error);
}