Вот мой взгляд на более общее решение:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
typedef int (*dirhandler_t)( const char*, void* );
/// calls itfunc for each directory in path (except for . and ..)
int iterate_path( const char* path, dirhandler_t itfunc, void* udata )
{
int rv = 0;
char tmp[ 256 ];
char *p = tmp;
char *lp = tmp;
size_t len;
size_t sublen;
int ignore_entry;
strncpy( tmp, path, 255 );
tmp[ 255 ] = '\0';
len = strlen( tmp );
if( 0 == len ||
(1 == len && '/' == tmp[ 0 ]) )
return 0;
if( tmp[ len - 1 ] == '/' )
tmp[ len - 1 ] = 0;
while( (p = strchr( p, '/' )) != NULL )
{
ignore_entry = 0;
*p = '\0';
lp = strrchr( tmp, '/' );
if( NULL == lp ) { lp = tmp; }
else { lp++; }
sublen = strlen( lp );
if( 0 == sublen ) /* ignore things like '//' */
ignore_entry = 1;
else if( 1 == sublen && /* ignore things like '/./' */
'.' == lp[ 0 ] )
ignore_entry = 1;
else if( 2 == sublen && /* also ignore things like '/../' */
'.' == lp[ 0 ] &&
'.' == lp[ 1 ] )
ignore_entry = 1;
if( ! ignore_entry )
{
if( (rv = itfunc( tmp, udata )) != 0 )
return rv;
}
*p = '/';
p++;
lp = p;
}
if( strcmp( lp, "." ) && strcmp( lp, ".." ) )
return itfunc( tmp, udata );
return 0;
}
mode_t get_file_mode( const char* path )
{
struct stat statbuf;
memset( &statbuf, 0, sizeof( statbuf ) );
if( NULL == path ) { return 0; }
if( 0 != stat( path, &statbuf ) )
{
fprintf( stderr, "failed to stat '%s': %s\n",
path, strerror( errno ) );
return 0;
}
return statbuf.st_mode;
}
static int mymkdir( const char* path, void* udata )
{
(void)udata;
int rv = mkdir( path, S_IRWXU );
int errnum = errno;
if( 0 != rv )
{
if( EEXIST == errno &&
S_ISDIR( get_file_mode( path ) ) ) /* it's all good, the directory already exists */
return 0;
fprintf( stderr, "mkdir( %s ) failed: %s\n",
path, strerror( errnum ) );
}
// else
// {
// fprintf( stderr, "created directory: %s\n", path );
// }
return rv;
}
int mkdir_with_leading( const char* path )
{
return iterate_path( path, mymkdir, NULL );
}
int main( int argc, const char** argv )
{
size_t i;
int rv;
if( argc < 2 )
{
fprintf( stderr, "usage: %s <path> [<path>...]\n",
argv[ 0 ] );
exit( 1 );
}
for( i = 1; i < argc; i++ )
{
rv = mkdir_with_leading( argv[ i ] );
if( 0 != rv )
return rv;
}
return 0;
}