示例#1
0
static int mkdir_nested( const char *path )
/*****************************************/
{
#ifdef __UNIX__
    struct stat sb;
#else
    unsigned    attr;
#endif
    char        pathname[ FILENAME_MAX ];
    char        *p;
    char        *end;

    p = pathname;
    strncpy( pathname, path, FILENAME_MAX );
    end = pathname + strlen( pathname );

#ifndef __UNIX__
    /* special case for drive letters */
    if( p[0] != '\0' && p[1] == ':' ) {
        p += 2;
    }
#endif
    /* skip initial path separator if present */
    if( (p[0] == '/') || (p[0] == '\\') )
        ++p;

    /* find the next path component */
    while( p < end ) {
        while( (p < end) && (*p != '/') && (*p != '\\') )
            ++p;
        *p = '\0';

        /* check if pathname exists */
#ifdef __UNIX__
        if( stat( pathname, &sb ) != 0 ) {
#else
        if( _dos_getfileattr( pathname, &attr ) != 0 ) {
#endif
            int rc;

#ifdef __UNIX__
            rc = mkdir( pathname, S_IRWXU | S_IRWXG | S_IRWXO );
#else
            rc = mkdir( pathname );
#endif
            if( rc != 0 ) {
                Log( false, "Can not create directory '%s': %s\n", pathname, strerror( errno ) );
                return( -1 );
            }
        } else {
            /* make sure it really is a directory */
#ifdef __UNIX__
            if( !S_ISDIR( sb.st_mode ) ) {
#else
            if( (attr & _A_SUBDIR) == 0 ) {
#endif
                Log( false, "Can not create directory '%s': file with the same name already exists\n", pathname );
                return( -1 );
            }
        }
        /* put back the path separator - forward slash always works */
        *p++ = '/';
    }
    return( 0 );
}

static int ProcOneCopy( const char *src, char *dst, bool cond_copy, char *copy_buff )
{
    FILE            *sp;
    FILE            *dp;
    size_t          len;
    size_t          out;
    struct stat     srcbuf;
    struct utimbuf  dstbuf;

    sp = fopen( src, "rb" );
    if( sp == NULL ) {
        if( cond_copy ) {
            return( 0 );    // Quietly ignore missing source
        } else {
            Log( false, "Can not open '%s' for reading: %s\n", src, strerror( errno ) );
            return( 1 );
        }
    }
    dp = fopen( dst, "wb" );
    if( dp == NULL ) {
        len = strlen( dst );
        while( len-- > 0 ) {
            char c = dst[len];
            if( c == '/' || c == '\\' ) {
                dst[len] = '\0';
                mkdir_nested( dst );
                dst[len] = c;
                dp = fopen( dst, "wb" );
                break;
            }
        }
        if( dp == NULL ) {
            Log( false, "Can not open '%s' for writing: %s\n", dst, strerror( errno ) );
            fclose( sp );
            return( 1 );
        }
    }
    Log( Quiet, "Copying '%s' to '%s'...\n", src, dst );
    while( (len = fread( copy_buff, 1, COPY_BUFF_SIZE, sp )) != 0 ) {
        if( ferror( sp ) ) {
            Log( false, "Error reading '%s': %s\n", src, strerror( errno ) );
            fclose( sp );
            fclose( dp );
            return( 1 );
        }
        out = fwrite( copy_buff, 1, len, dp );
        if( ferror( dp ) ) {
            Log( false, "Error writing '%s': %s\n", dst, strerror( errno ) );
            fclose( sp );
            fclose( dp );
            return( 1 );
        }
        if( out != len ) {
            Log( false, "Error writing '%s': Disk full\n", dst );
            fclose( sp );
            fclose( dp );
            return( 1 );
        }
    }
    fclose( sp );
    fclose( dp );

    /* make real copy, set the date back */
    stat( src, &srcbuf );
    dstbuf.actime = srcbuf.st_atime;
    dstbuf.modtime = srcbuf.st_mtime;
    utime( dst, &dstbuf );
#ifdef __UNIX__
    /* copy permissions: mostly necessary for the "x" bit */
    // some files is copied from the source tree with the read-only permission
    // for next run we need the write permission for the current user as minimum
    chmod( dst, srcbuf.st_mode | S_IWUSR );
#endif
    return( 0 );
}

static int ProcCopy( char *cmd, bool test_abit, bool cond_copy, bool ignore_errors )
{
    char        *dst;
    copy_entry  *list;
    copy_entry  *next;
    int         res;

    for( dst = cmd; *dst != '\0'; ++dst ) {
        if( IS_BLANK( *dst ) ) {
            *dst++ = '\0';
            dst = SkipBlanks( dst );
            break;
        }
    }
    if( *dst == '\0' ) {
        Log( false, "Missing parameter\n" );
        return( 1 );
    }
    res = BuildList( cmd, dst, test_abit, cond_copy, &list );
    if( res == 0 && list != NULL ) {
        char    *copy_buff = Alloc( COPY_BUFF_SIZE );
        for( ; list != NULL; list = next ) {
            next = list->next;
            if( res == 0 || ignore_errors ) {
                int     rc;

                rc = ProcOneCopy( list->src, list->dst, cond_copy, copy_buff );
                if( rc != 0 ) {
                    res = rc;
#ifndef __UNIX__
                } else if( test_abit ) {
                    list->next = IncludeStk->reset_abit;
                    IncludeStk->reset_abit = list;
                    continue;
#endif
                }
            }
            free( list );
        }
        free( copy_buff );
    }
    return( res );
}
示例#2
0
static int mkdir_nested( char *path )
/***********************************/
{
#ifdef __UNIX__
    struct stat sb;
#else
    unsigned    attr;
#endif
    char        pathname[ FILENAME_MAX ];
    char        *p;
    char        *end;

    p = pathname;
    strncpy( pathname, path, FILENAME_MAX );
    end = pathname + strlen( pathname );

#ifndef __UNIX__
    /* special case for drive letters */
    if( p[0] && p[1] == ':' ) {
        p += 2;
    }
#endif
    /* skip initial path separator if present */
    if( (p[0] == '/') || (p[0] == '\\') )
        ++p;

    /* find the next path component */
    while( p < end ) {
        while( (p < end) && (*p != '/') && (*p != '\\') )
            ++p;
        *p = '\0';

        /* check if pathname exists */
#ifdef __UNIX__
        if( stat( pathname, &sb ) == -1 ) {
#else
        if( _dos_getfileattr( pathname, &attr ) != 0 ) {
#endif
            int rc;

#ifdef __UNIX__
            rc = mkdir( pathname, S_IRWXU | S_IRWXG | S_IRWXO );
#else
            rc = mkdir( pathname );
#endif
            if( rc != 0 ) {
                Log( FALSE, "Can not create directory '%s': %s\n", pathname, strerror( errno ) );
                return( -1 );
            }
        } else {
            /* make sure it really is a directory */
#ifdef __UNIX__
            if( !S_ISDIR( sb.st_mode ) ) {
#else
            if( (attr & _A_SUBDIR) == 0 ) {
#endif
                Log( FALSE, "Can not create directory '%s': file with the same name already exists\n", pathname );
                return( -1 );
            }
        }
        /* put back the path separator - forward slash always works */
        *p++ = '/';
    }
    return( 0 );
}

static unsigned ProcOneCopy( char *src, char *dst, bool cond_copy )
{
    FILE            *sp;
    FILE            *dp;
    unsigned        len;
    unsigned        out;
    struct stat     srcbuf;
    struct utimbuf  dstbuf;
    static char     buff[32 * 1024];

    sp = fopen( src, "rb" );
    if( sp == NULL ) {
        if( cond_copy ) {
            return( 0 );    // Quietly ignore missing source
        } else {
            Log( FALSE, "Can not open '%s' for reading: %s\n", src, strerror( errno ) );
            return( 1 );
        }
    }
    dp = fopen( dst, "wb" );
    if( dp == NULL ) {
        char *end1, *end2, *end;

        strcpy( buff, dst );
        end1 = strrchr( buff, '/' );
        end2 = strrchr( buff, '\\' );
        if( end1 && end2 ) {
            if( end1 > end2 )
                end = end1;
            else
                end = end2;
        } else if( end1 ) {
            end = end1;
        } else {
            end = end2;
        }
        if( end ) {
            end[0] = 0;
            mkdir_nested( buff );
            dp = fopen( dst, "wb" );
        }
        if( !dp ) {
            Log( FALSE, "Can not open '%s' for writing: %s\n", dst, strerror( errno ) );
            fclose( sp );
            return( 1 );
        }
    }
    Log( FALSE, "Copying '%s' to '%s'...\n", src, dst );
    for( ;; ) {
        len = fread( buff, 1, sizeof( buff ), sp );
        if( len == 0 )
            break;
        if( ferror( sp ) ) {
            Log( FALSE, "Error reading '%s': %s\n", src, strerror( errno ) );
            fclose( sp );
            fclose( dp );
            return( 1 );
        }
        out = fwrite( buff, 1, len, dp );
        if( ferror( dp ) ) {
            Log( FALSE, "Error writing '%s': %s\n", dst, strerror( errno ) );
            fclose( sp );
            fclose( dp );
            return( 1 );
        }
        if( out != len ) {
            Log( FALSE, "Error writing '%s': Disk full\n", dst );
            fclose( sp );
            fclose( dp );
            return( 1 );
        }
    }
    fclose( sp );
    fclose( dp );

    /* make real copy, set the date back */
    stat( src, &srcbuf );
    dstbuf.actime = srcbuf.st_atime;
    dstbuf.modtime = srcbuf.st_mtime;
    utime( dst, &dstbuf );
#ifdef __UNIX__
    /* copy permissions: mostly necessary for the "x" bit */
    // some files is copied from the source tree with the read-only permission
    // for next run we need the write permission for the current user as minimum
    chmod( dst, srcbuf.st_mode | S_IWUSR );
#endif
    return( 0 );
}

static unsigned ProcCopy( char *cmd, bool test_abit, bool cond_copy )
{
    char        *src;
    char        *dst;
    copy_entry  *list;
    copy_entry  *next;
    unsigned    res;

    src = cmd;
    dst = strchr( src, ' ' );
    if( dst == NULL ) {
        dst = strchr( src, '\t' );
        if( dst == NULL ) {
            Log( FALSE, "Missing destination parameter\n" );
            return( 1 );
        }
    }
    *dst = '\0';
    dst = SkipBlanks( dst + 1 );
    if( *dst == '\0' ) {
        Log( FALSE, "Missing destination parameter\n" );
        return( 1 );
    }
    list = BuildList( src, dst, test_abit );
    for( ;; ) {
        if( list == NULL )
            break;
        res = ProcOneCopy( list->src, list->dst, cond_copy );
        if( res != 0 ) {
            while( list != NULL ) {
                next = list->next;
                free( list );
                list = next;
            }
            return( res );
        }
        next = list->next;
        if( test_abit ) {
            list->next = IncludeStk->reset_abit;
            IncludeStk->reset_abit = list;
        } else {
            free( list );
        }
        list = next;
    }
    return( 0 );
}