compress.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 996 行 · 第 1/3 页

C
996
字号

    /* Unsuccessful return -- one of the tests failed */
    if( unlink( ofname ) )
    perror( ofname );
}

static void compress_file( char **fileptr )
/*****************************************/
{
    char    tempname[MAXPATHLEN];
#ifdef SHORTNAMES
    char    *cp;
#endif

    strcpy( tempname, *fileptr );
    errno = 0;
    if( stat( tempname, &insbuf ) == -1 ) {
        if( do_decomp ) {
            switch( errno ) {
            case ENOENT:    /* file doesn't exist */
                /*
                ** if the given name doesn't end with .Z, try appending one
                ** This is obviously the wrong thing to do if it's a
                ** directory, but it shouldn't do any harm.
                */
                if( stricmp( tempname + strlen( tempname ) - 2, ".Z" ) != 0 ) {
#ifdef SHORTNAMES
                    if( (cp = strrchr( tempname, DIR_SEP_CHAR ) ) != NULL )
                        cp++;
                    else                    
                        cp = tempname;
                    if( strlen( cp ) > 12 ) {
                        fprintf( stderr, "%s.Z: No such file or directory\n", tempname );
                        return;
                    }
#endif  /* SHORTNAMES */
                    strcat( tempname, ".Z" );
                    errno = 0;
                    if( stat( tempname, &insbuf ) == -1 ) {
                        perror( tempname );
                        return;
                    }
                } else {
                    perror( tempname );
                    return;
                }
                break;
            default:
                perror( tempname );
                return;
            }
        } else {
            /* we can't stat the file, ignore it */
            perror( tempname );
            return;
        }
    }

    switch( insbuf.st_mode & S_IFMT ) {
    case S_IFDIR:   /* directory */
        if( !quiet )
            fprintf( stderr, "%s is a directory -- ignored\n", tempname );
        break;
    case S_IFREG:   /* regular file */
        exit_stat = 0;
        if( do_decomp != 0 ) {
            /* DECOMPRESSION */
            if( !zcat_flg ) {
                if( stricmp( tempname + strlen( tempname ) - 2, ".Z" ) != 0 ) {
                    if( !quiet ) {
                        fprintf( stderr, "%s - no .Z suffix\n", tempname );
                    }
                    return;
                }
            }
            /* Open input file */
            if( freopen( tempname, "rb", stdin ) == NULL ) {
                perror( tempname );
                return;
            }
            setvbuf( stdin, NULL, _IOFBF, IO_BUF_SIZE );
            /* Check the magic number */
            if( nomagic == 0 ) {
                if ((getchar() != (magic_header[0] & 0xFF))
                 || (getchar() != (magic_header[1] & 0xFF))) {
                    fprintf( stderr, "%s: not in compressed format\n", tempname );
                    return;
                }
                maxbits = getchar();    /* set -b from file */
                block_compress = maxbits & BLOCK_MASK;
                maxbits &= BIT_MASK;
                maxmaxcode = 1 << maxbits;
                if( maxbits > BITS ) {
                    fprintf( stderr,
                         "%s: compressed with %d bits, can only handle %d bits\n",
                         tempname, maxbits, BITS );
                    return;
                }
            }
            /* we have to ignore SIGINT for a while, otherwise
             * a ^C can nuke an existing file with ofname
             */
            signal( SIGINT, SIG_IGN );
            /* Generate output filename */
            strcpy( ofname, tempname );
            /* Check for .Z suffix */
            if( stricmp( tempname + strlen( tempname ) - 2, ".Z" ) == 0 ) {
                ofname[strlen( tempname ) - 2] = '\0';  /* Strip off .Z */
            }
        } else {
            /* COMPRESSION */
            if( stricmp( tempname + strlen( tempname ) - 2, ".Z" ) == 0 ) {
                fprintf( stderr, "%s: already has .Z suffix -- no change\n",
                         tempname);
                return;
            }
            if( insbuf.st_nlink > 1 && (!force) ) {
                fprintf( stderr, "%s has %d other links: unchanged\n",
                         tempname, insbuf.st_nlink - 1 );
                return;
            }
            /* Open input file */
            if( freopen( tempname, "rb", stdin ) == NULL ) {
                perror( tempname );
                return;
            }
            fsize = (long)insbuf.st_size;
            /*
             * 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.
             */
            hsize = HSIZE;
            if( fsize < (1 << 12) )
                hsize = min( 5003, HSIZE );
            else if( fsize < (1 << 13) )
                hsize = min( 9001, HSIZE );
            else if( fsize < (1 << 14) )
                hsize = min( 18013, HSIZE );
            else if( fsize < (1 << 15) )
                hsize = min( 35023, HSIZE );
            else if( fsize < 47000 )
                hsize = min( 50021, HSIZE );

            /* we have to ignore SIGINT for a while, otherwise
             * a ^C can nuke an existing file with ofname
             */
            signal( SIGINT, SIG_IGN );
            /* Generate output filename */
            strcpy( ofname, tempname );
#ifdef SHORTNAMES   /* Short filenames */
            if( (cp = strrchr( ofname, DIR_SEP_CHAR ) ) != NULL )
                cp++;
            else
                cp = ofname;
            if( strlen( cp ) > 12 ) {
                fprintf( stderr, "%s: filename too long to tack on .Z\n", ofname );
                signal( SIGINT, onintr );
                return;
            }
#endif  /* SHORTNAMES */
            strcat( ofname, ".Z" );
        }
        /* Check for overwrite of existing file */
        if( overwrite == 0 && zcat_flg == 0 ) {
            if( stat( ofname, &statbuf ) == 0 ) {
                char    response[2];
            
                response[0] = 'n';
                fprintf( stderr, "%s already exists;", ofname );
                if( foreground() ) {
                    fprintf( stderr, " OK to overwrite (y or n)? " );
                    fflush( stderr );
                    read( 2, response, 2 );
                    while( response[1] != '\n' ) {
                        if( read( 2, response + 1, 1 ) < 0 ) {  /* Ack! */
                            perror( "stderr" );
                            break;
                        }
                    }
                }
                if( response[0] != 'y' ) {
                    fprintf( stderr, "\tnot overwritten\n" );
                    signal( SIGINT, onintr );
                    return;
                }
            }
        }
        signal( SIGINT, onintr );
        if( zcat_flg == 0 ) {       /* Open output file */
            valid = 1;
        if( freopen( ofname, "wb", stdout ) == NULL ) {
            perror( ofname );
            return;
        }
        if( !quiet )
            fprintf( stderr, "%s: ", tempname );
        } else {
            setmode( fileno( stdout ), O_BINARY );
        }
        setvbuf( stdout, NULL, _IOFBF, IO_BUF_SIZE );

        /* Actually do the compression/decompression */
        if( do_decomp == 0 )    
            compress();
        else            
            decompress();
        if( zcat_flg == 0 ) {
            copystat( tempname, ofname );   /* Copy stats */
        if( (exit_stat == 1) || (!quiet) )
            putc( '\n', stderr );
        }
        break;
    default:
        fprintf( stderr,"%s is not a directory or a regular file - ignored\n",
                 tempname );
        break;
    }
}

static int is_this( char *pathname, const char *name )
/****************************************************/
{
    const char  *base = basename( pathname );

#ifdef __UNIX__
    return( !strcmp( base, name ) );
#else
    return( !strnicmp( base, name, strlen( name ) ) );
#endif
}

int main( int argc, char **argv )
/*******************************/
{
    int     ch;

    if( (bgnd_flag = signal( SIGINT, SIG_IGN )) != SIG_IGN ) {
        signal( SIGINT, onintr );
    }
    signal( SIGSEGV, oops );

    if( is_this( argv[0], "uncompress" ) ) {
        do_decomp = 1;
    } else if( is_this( argv[0], "zcat" ) ) {
        do_decomp = 1;
        zcat_flg = 1;
    }

    while( (ch = getopt( argc, argv, ":b:cdfv" )) != -1 ) {
        switch( ch ) {
        case 'b':
            maxbits = atoi( optarg );
            break;
        case 'c':
            zcat_flg = 1;
            break;
        case 'C':
            block_compress = 0;
            break;
        case 'd':
            do_decomp = 1;
            break;
        case 'f':
            overwrite = 1;
            force = 1;
            break;
        case 'n':
            nomagic = 1;
            break;
        case 'v':
            quiet = 0;
            break;
        case 'q':
            quiet = 1;
            break;
        case ':':
            util_quit( usage_text, "missing maxbits\n" );
        case '?':
            util_quit( usage_text, NULL );
        }
    }

    /* Skip option arguments and argv[0] */
    argc = argc - optind;
    argv += optind;

    if( maxbits < INIT_BITS )
        maxbits = INIT_BITS;
    if( maxbits > BITS )
        maxbits = BITS;
    maxmaxcode = 1 << maxbits;

    if( *argv != NULL ) {
        for( ; *argv; ++argv ) {
            compress_file( argv );
        }
    } else {        /* Standard input */
        setmode( fileno( stdin ), O_BINARY );
        setmode( fileno( stdout ), O_BINARY );
        setvbuf( stdin, NULL, _IOFBF, IO_BUF_SIZE );
        setvbuf( stdout, NULL, _IOFBF, IO_BUF_SIZE );
        if( do_decomp == 0 ) {
            compress();
            if( !quiet )
                putc( '\n', stderr );
        } else {
            /* Check the magic number */
            if( nomagic == 0 ) {
                if( (getchar() != (magic_header[0] & 0xFF))
                 || (getchar() != (magic_header[1] & 0xFF)) ) {
                    fprintf( stderr, "stdin: not in compressed format\n" );
                    return( 1 );
                }
                maxbits = getchar();    /* set -b from file */
                block_compress = maxbits & BLOCK_MASK;
                maxbits &= BIT_MASK;
                maxmaxcode = 1 << maxbits;
                fsize = 100000;     /* assume stdin large for USERMEM */
                if( maxbits > BITS ) {
                    fprintf( stderr,
                        "stdin: compressed with %d bits, can only handle %d bits\n",
                        maxbits, BITS );
                    return( 1 );
                }
            }
            decompress();
        }
    }
    return( exit_stat );
}

⌨️ 快捷键说明

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