cpio.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 452 行

C
452
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Performs enhanced Unix cp file I/O.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <io.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/utime.h>
#include <dos.h>
#if defined(__OS_os2386__)
#define  INCL_DOSFILEMGR
#define  INCL_DOSERRORS
#define  INCL_DOSMISC
#include <os2.h>
#endif
#include "cp.h"

/*
 * GrabFile - read in a specified file, dump it to destination
 */
int GrabFile( char *src, struct stat *stat_s, char *dest, char srcattr )
{
#if defined(__OS_os2386__)
    int                 result;
#else
    ctrl_block          *cb;
#endif
    int                 handle;
    int                 okay=TRUE;
    timedate            td;
    unsigned short      t,d;

    /*
     * file handle
     */
    if( _dos_open( src, O_RDONLY, &handle ) ) {
        DropPrintALine( "Error opening file %s",src );
        IOError( errno );
    }

    /*
     * get time/date stamp of file
     */
    if( npflag || todflag ) {
        _dos_getftime( handle, &d, &t );
        if( todflag ) {
            td.yy = (((d & 0xFE00) >> 9) + 1980);
            td.mm = ((d & 0x01E0 ) >> 5);
            td.dd = (d & 0x001F);
            td.hr = ((t & 0xF800) >> 11);
            td.min = ((t & 0x07E0) >> 5);
            td.sec = ((t & 0x001F) << 1);
            /*
             * see if this file passes the date checks
             */
            if( tflag2 ) {
                if( td.hr <= after_t_d.hr ) {
                    if( td.hr < after_t_d.hr ) {
                        return( FALSE );
                    }
                    if( td.min <= after_t_d.min ) {
                        if( td.min < after_t_d.min ) {
                            return( FALSE );
                        }
                        if( td.sec < after_t_d.sec ) {
                            return( FALSE );
                        }
                    }
                }
            }
            if( Tflag1 ) {
                if( td.hr >= before_t_d.hr ) {
                    if( td.hr > before_t_d.hr ) {
                        return( FALSE );
                    }
                    if( td.min >= before_t_d.min ) {
                        if( td.min > before_t_d.min ) {
                            return( FALSE );
                        }
                        if( td.sec > before_t_d.sec ) {
                            return( FALSE );
                        }
                    }
                }
            }
            if( dflag2 ) {
                if( td.yy <= after_t_d.yy ) {
                    if( td.yy < after_t_d.yy ) {
                        return( FALSE );
                    }
                    if( td.mm <= after_t_d.mm ) {
                        if( td.mm < after_t_d.mm ) {
                            return( FALSE );
                        }
                        if( td.dd < after_t_d.dd ) {
                            return( FALSE );
                        }
                    }
                }
            }
            if( Dflag1 ) {
                if( td.yy >= before_t_d.yy ) {
                    if( td.yy > before_t_d.yy ) {
                        return( FALSE );
                    }
                    if( td.mm >= before_t_d.mm ) {
                        if( td.mm > before_t_d.mm ) {
                            return( FALSE );
                        }
                        if( td.dd > before_t_d.dd ) {
                            return( FALSE );
                        }
                    }
                }
            }
        }
    }

#if defined(__OS_os2386__)
    if( !sflag ) {
        PrintALineThenDrop( "Copying file %s to %s", src, dest );
    }
    srcattr = srcattr;
    _dos_close( handle );
    /*
     * perform the copy - OS/2 preserves attributes and time stamp
     */
    result = DosCopy( src, dest, DCPY_EXISTING );
    if( result ) {
        OS2Error( result );
    }
    /*
     * update the time stamp if required
     */
    if( !npflag ) {
        if( !(stat_s->st_mode & S_IWRITE) ) {
            chmod( dest, S_IWRITE | S_IREAD );
        }
        result = utime( dest, NULL );
        if( result < 0 ) {
            DropPrintALine( "Error updating time for %s", dest );
            IOError( errno );
        }
        if( pattrflag && !(stat_s->st_mode & S_IWRITE) ) {
            chmod( dest, S_IREAD );
        }
    } else {
        if( !pattrflag && !(stat_s->st_mode & S_IWRITE) ) {
            chmod( dest, S_IWRITE | S_IREAD );
        }
    }
#else
    /*
     * get memory for control block
     */
    cb = NearAlloc( sizeof( ctrl_block ) );
    cb->inname = NearAlloc( strlen( src ) + 1 );
    cb->outname = NearAlloc( strlen( dest ) + 1 );

    /*
     * set cb info
     */
    strcpy( cb->inname, src );
    strcpy( cb->outname, dest );
    cb->bytes_pending = stat_s->st_size;
    cb->head = cb->curr = NULL;
    cb->outhandle = -1;
    cb->inhandle = handle;
    cb->prev = cb->next = NULL;
    cb->srcattr = srcattr;
    if( npflag ) {
        cb->t = t;
        cb->d = d;
    }
    if( !sflag ) {
        PrintALine( "reading file %s (%ld bytes)", cb->inname, cb->bytes_pending );
    }

    /*
     * chain into list of cb's
     */
    if( CBHead == NULL ) {
        CBHead = CBTail = cb;
    } else {
        CBTail->next = cb;
        cb->prev = CBTail;
        CBTail = cb;
    }

    /*
     * process the file
     */
    while( cb->bytes_pending ) {
        if( !readABuffer() ) {
            freeCB( cb, TRUE );
            okay = FALSE;
            break;
        }
    }
    _dos_close( cb->inhandle );
#endif
    if( okay ) {
        FileCnt++;
    }
    return( okay );

} /* GrabFile */

#if !defined(__OS_os2386__)
/*
 * readABuffer - read a data buffer
 */
static int readABuffer( void )
{
    char        __FAR *buff;
    unsigned    buffsize;
    mem_block   *mb;
    int         flushed = FALSE;
    unsigned    bytes;

    /*
     * get buffer size
     */
    if( CBTail->bytes_pending > (long) MAXIOBUFFER ) {
        buffsize = MAXIOBUFFER;
    } else {
        buffsize = (unsigned) CBTail->bytes_pending;
    }

    /*
     * get buffer
     */
    while( TRUE ) {
        buff = FarAlloc( buffsize );
        if( buff != NULL ) {
            break;
        }
        if( flushed ) {
            Die( "Out of FAR memory!\n" );
        }
        FlushMemoryBlocks();
        if( !sflag ) {
            PrintALine( "continuing read of %s (%ld more bytes)", CBTail->inname, CBTail->bytes_pending );
        }
        flushed = TRUE;
    }

    /*
     * read data
     */
    if( _dos_read( CBTail->inhandle, buff, buffsize, &bytes ) ||
                bytes != buffsize ) {
        DropPrintALine( "Read error on file %s", CBTail->inname );
        IOError( errno );
    }
    CBTail->bytes_pending -= (long) buffsize;

    /*
     * allocate memory block
     */
    mb = NearAlloc( sizeof( mem_block ) );
    mb->in_memory = TRUE;
    mb->where.buffer = buff;
    mb->next = NULL;
    mb->buffsize = buffsize;
    if( CBTail->head == NULL ) {
        CBTail->head = CBTail->curr = mb;
    } else {
        CBTail->curr->next = mb;
        CBTail->curr = mb;
    }

    return( TRUE );

} /* readABuffer */
#endif

/*
 * freeCB - free a control block
 */
static void freeCB( ctrl_block *cb, int freecb )
{
    mem_block   *mb,*tmb;

    /*
     * free all memory information
     */
    mb = cb->head;
    while( mb != NULL ) {
        tmb = mb->next;
        if( mb->in_memory ) {
            FarFree( mb->where.buffer );
        }
        NearFree( mb );
        mb = tmb;
    }

    /*
     * take ctrl block out of chain
     */
    if( !freecb ) {
        cb->head = NULL;
        return;
    }
    if( cb == CBHead ) {
        CBHead = cb->next;
    }
    if( cb == CBTail ) {
        CBTail = cb->prev;
    }
    if( cb->prev != NULL ) {
        cb->prev->next = cb->next;
    }
    if( cb->next != NULL ) {
        cb->next->prev = cb->prev;
    }
    NearFree( cb->inname );
    NearFree( cb->outname );
    NearFree( cb );

} /* freeCB */

/*
 * FlushMemoryBlocks - write all pending files
 */
void FlushMemoryBlocks()
{
    ctrl_block          *curr,*tmp;
    char                __FAR *buff;
    mem_block           *mb;
    long                total=0;
    unsigned            bytes;
    time_t              timetaken;
    time_t              secs,hunds;

    curr = CBHead;
    if( curr == NULL ) {
        return;
    }
    while( curr != NULL ) {
        /*
         * open file if we have to
         */
        if( curr->outhandle < 0 ) {
//          if( _dos_creat( curr->outname, _A_NORMAL, &curr->outhandle ) ) {
            curr->outhandle = creat( curr->outname, S_IRWXU  );
            if( curr->outhandle < 0 ) {
                DropPrintALine( "Error opening destination file %s",curr->outname );
                IOError( errno );
            }
            if( !sflag ) {
                PrintALine( "writing file %s", curr->outname );
            }
        } else {
            if( !sflag ) {
                PrintALine( "continuing write of %s", curr->outname );
            }
        }

        /*
         * write the buffer
         */
        mb = curr->head;
        while( mb != NULL ) {
            if( mb->in_memory ) {
                buff = mb->where.buffer;
            }
            total += (long) mb->buffsize;
            if( _dos_write( curr->outhandle, buff, mb->buffsize, &bytes ) ||
                        bytes != mb->buffsize ) {
                DropPrintALine( "Error writing destination file %s",curr->outname );
                IOError( errno );
            }
            mb = mb->next;
        }
        if( curr->bytes_pending == 0 ) {
            if( npflag ) {
                _dos_setftime( curr->outhandle, curr->d, curr->t  );
            }
            close( curr->outhandle );
            if( pattrflag ) {
                _dos_setfileattr( curr->outname, curr->srcattr );
            }
        }

        /*
         * now get rid of the info with this block
         */
        tmp = curr;
        curr = curr->next;
        freeCB( tmp, (tmp->bytes_pending == 0L) );
    }

    if( !sflag ) {

        DumpCnt++;

        timetaken = clock() - StartTime;
        StartTime = clock();
        secs = (timetaken/CLOCKS_PER_SEC);
        hunds = timetaken-secs*CLOCKS_PER_SEC;

        if( rflag ) {
            PrintALineThenDrop( "%ld bytes, %u files written, %u dirs created in %ld.%ld seconds (dump %u)",
                            total, FileCnt, DirCnt, secs, hunds, DumpCnt );
        } else {
            PrintALineThenDrop( "%ld bytes, %u files written in %ld.%02ld seconds (dump %u)",
                            total, FileCnt, secs, hunds, DumpCnt );
        }
        TotalBytes += total;
        TotalFiles += FileCnt;
        TotalDirs += DirCnt;
        TotalTime += timetaken;
        FileCnt = 0;
        DirCnt = 0;
    }

} /* FlushMemoryBlocks */

⌨️ 快捷键说明

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