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 ); }
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 ); }