cpfile.c

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

C
400
字号
/****************************************************************************
*
*                            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 <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h>
#include <conio.h>
#include <errno.h>
#include <dos.h>
#include <direct.h>
#if defined(__OS_os2386__)
#define  INCL_DOSFILEMGR
#define  INCL_DOSERRORS
#define  INCL_DOSMISC
#include <os2.h>
#endif
#if defined(__OS_nt386__) || defined( __OS_ntaxp__ )
#include <windows.h>
#endif
#include "cp.h"
#include "filerx.h"
#include "fnutils.h"

#if defined(__OS_dosos2__) || defined(__OS_dos__) || defined(__OS_pharlap__)
extern long DosGetFullPath( char __FAR *org, char __FAR *real );
#pragma aux DosGetFullPath = \
        "push   ds" \
        "mov    si,ax" \
        "mov    ds,dx" \
        "mov    ah,60H" \
        "int    21h" \
        "sbb    dx,dx" \
        "pop    ds" \
        parm [dx ax] [es di] value [dx ax] modify[si];

/*
 * dosSameFile - DOS specific same file test
 */
int dosSameFile( char *dest, char *src )
{
#define strcmp(p1,p2)           _inline_strcmp(p1,p2)
extern int _inline_strcmp( char *, char * );
    char        fullsrc[_MAX_PATH];
    char        fulldest[_MAX_PATH];

    DosGetFullPath( dest, fulldest );
    DosGetFullPath( src, fullsrc );
    if( !strcmp( fulldest, fullsrc ) ) {
        return( TRUE );
    }
    return( FALSE );

} /* dosSameFile */

/*
 * osSameFile - OS/2 specific same file test
 */
static int osSameFile( char *dest, char *src )
{
    if( _osmode == DOS_MODE ) {
        return( dosSameFile( dest, src ) );
    }
    src = src;
    dest = dest;
    return( TRUE );

} /* osSameFile */

#elif defined(__OS_nt386__) || defined(__OS_ntaxp__)
/*
 * osSameFile - NT specific same file test
 */
static int osSameFile( char *dest, char *src )
{
    char *fp;
    char        fullsrc[MAX_PATH];
    char        fulldest[MAX_PATH];

    GetFullPathName( dest, MAX_PATH, fulldest, &fp );
    GetFullPathName( src, MAX_PATH, fullsrc, &fp );
    if( !stricmp( fulldest, fullsrc ) ) {
        return( TRUE );
    }
    return( FALSE );

} /* osSameFile */

#endif

#if !defined(__OS_os2386__)
/*
 * sameFile - test if two files are the same
 */
static int sameFile( char *dest, struct stat *ds, char *src, struct stat *ss )
{
    if( ds->st_size == ss->st_size ) {
        if( ds->st_atime == ss->st_atime ) {
            if( ds->st_dev == ss->st_dev ) {
                if( ds->st_mode == ss->st_mode ) {
                    return( osSameFile( dest, src ) );
                }
            }
        }
    }
    return( FALSE );

} /* sameFile */
#endif


/*
 * head is a buffer of size _MAX_PATH.
 * tail points at null terminator of head.
 * to_append is a string that is to be appended to head.
 */
static char *pathCopy( char *head, char *tail, const char *to_append ) {

    size_t      len;

    len = strlen( to_append );
    if( ( tail + len ) - head >= _MAX_PATH ) {
        *tail = 0;
        Die( "Path too long: %s%s\n", head, to_append );
    }
    return( (char *)memcpy( tail, to_append, len + 1 ) + len );
}


/*
 * recursiveCp - copy a file to a directory (recursively entered)
 *
 * source_head  points to a buffer of size _MAX_PATH that ends with a ':'
 *              or a FILESEP.
 * source_tail  points to the null terminator of source_head.
 * source_wild  is the filename/pattern to append to source_head to get the
 *              names of the file(s) to copy.
 * dest_head    points to a buffer of size _MAX_PATH that ends with a ':'
 *              or a FILESEP
 * dest_tail    points to the null terminator of dest_head.
 *
 * Note that the buffers source_head/dest_head are passed down the
 * recursion to save stack space.
 */
static void recursiveCp( char *source_head, char *source_tail,
    char *source_wild, char *dest_head, char *dest_tail )
{

    DIR                 *directory;
    struct dirent       *nextdirentry;
    void                *crx;
    char                *new_source_tail;
    char                *new_dest_tail;

    pathCopy( source_head, source_tail, "*.*" );

    directory = opendir( source_head );
    if( directory == NULL ) {
        DropPrintALine( "file \"%s\" not found", source_head );
        return;
    }

    if( rxflag ) {
        char *err = FileMatchInit( &crx, source_wild );
        if( err != NULL ) {
            Die( "\"%s\": %s\n", err, source_wild );
        }
    }

    /*
     * loop through all files
     */
    while( ( nextdirentry = readdir( directory ) ) != NULL ) {
        /*
         * set up file name, then try to copy it
         */
        FNameLower( nextdirentry->d_name );
        if( rxflag ) {
            if( !FileMatch( crx, nextdirentry->d_name ) ) {
                continue;
            }
        } else {
            if( !FileMatchNoRx( nextdirentry->d_name, source_wild ) ) {
                continue;
            }
        }
        new_source_tail = pathCopy( source_head, source_tail,
            nextdirentry->d_name );
        new_dest_tail = pathCopy( dest_head, dest_tail, nextdirentry->d_name );

        if( nextdirentry->d_attr & _A_SUBDIR ) {

            if( !IsDotOrDotDot( nextdirentry->d_name ) && rflag ) {
                int     rc;

                rc = mkdir( dest_head );
                if( !rc ) {
                    DirCnt++;
                }
                if( !sflag ) {
                    if( rc ) {
                        PrintALineThenDrop( "directory %s already exists",
                            dest_head );
                    } else {
                        PrintALineThenDrop( "created new directory %s",
                            dest_head );
                    }
                }
                new_dest_tail = pathCopy( dest_head, new_dest_tail,
                    FILESEPSTR );
                new_source_tail = pathCopy( source_head, new_source_tail,
                    FILESEPSTR );
                recursiveCp( source_head, new_source_tail,
                    rxflag ? "*" : "*.*",
                    dest_head, new_dest_tail );
            }

        } else {

            CopyOneFile( dest_head, source_head );

        }

    }
    closedir( directory );
    if( rxflag ) {
        FileMatchFini( crx );
    }

} /* DoCP */


/*
 * DoCP - copy a file to a directory
 */
void DoCP( char *f, char *dir )
{
    char                source_buf[ _MAX_PATH ];
    char                *source_tail;
    char                dest_buf[ _MAX_PATH ];
    char                *dest_tail;
    int                 i = strlen( f );

    /*
     * get file path prefix
     */
    source_tail = source_buf;
    while( --i >= 0 ) {
        if( f[i] == ':' || isFILESEP( f[i] ) ) {
            source_tail = (char *)memcpy( source_buf, f, i + 1 ) + i + 1;
            break;
        }
    }
    *source_tail = 0;
    strcpy( dest_buf, dir );
    dest_tail = dest_buf + strlen( dest_buf );
    recursiveCp( source_buf, source_tail, f + i + 1, dest_buf, dest_tail );

} /* DoCP */


/*
 * CopyOneFile  - copy one file to another
 */
void CopyOneFile( char *dest, char *src )
{


    struct stat stat_s,stat_d;
    int         i;
    unsigned    srcattr;

    /*
     * first, check if source exists
     */
    if( stat( src,&stat_s ) == - 1 ) {
        DropPrintALine("file \"%s\" not found.",src );
        return;
    }
    _dos_getfileattr( src, &srcattr );

    /*
     * check if the archive bit is set; if not, go back
     */
    if( aflag ) {
        if( !(srcattr & _A_ARCH) ) {
            return;
        }
    }

    /*
     * if destination exists, make sure we can overwrite it
     */
    if( stat( dest,&stat_d ) != -1 ) {

#if !defined(__OS_os2386__)
        if( sameFile( dest, &stat_d, src, &stat_s ) ) {
            DropPrintALine( "%s and %s the same file, copy failed",src,dest );
            return;
        }
#endif

        if( !(stat_d.st_mode & S_IWRITE) ) {
            if( !fflag ) {
                DropPrintALine( "destination file %s is read only - use cp -f", dest);
                return;
            } else {
                chmod( dest, S_IWRITE | S_IREAD );
            }
        }

        if( iflag ) {
            PrintALine( "overwrite %s (y\\n)", dest );
            i = 0;
            while( i != 'y' && i != 'n' ) {
                i=getch();
            }
            DropALine();
            if( i=='n' ) {
                return;
            }
        }

    }

    /*
     * copy the file, and if it works, reset archive flag
     * of source (if needed)
     */
    if( !GrabFile( src, &stat_s, dest, srcattr ) ) {
        return;
    }

    if( aflag ) {
        _dos_setfileattr( src, srcattr & (~_A_ARCH) );
    }

} /* CopyOneFile */

/*
 * IOError - fatal I/O error encountered
 */
void IOError( int error )
{
    printf( "\nDOS error[%d] %s\n", error, strerror( error ) );
    exit( 1 );

} /* IOError */

#if defined(__OS_os2386__)
/*
 * OS2Error - fatal I/O error encountered
 */
void OS2Error( int error )
{
    #define MAX_MSG 128
    char buffer[MAX_MSG];
    unsigned long len;

    DosGetMessage( NULL, 0, buffer, MAX_MSG, error, "OSO001.MSG", &len );
    buffer[len] = '\0';
    printf( "%s", buffer );
    exit( 1 );

} /* OS2Error */
#endif

⌨️ 快捷键说明

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