|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "jam.h" |
|
|
#ifdef OS_NT |
|
|
#include "filesys.h" |
|
|
|
|
|
#include "object.h" |
|
|
#include "pathsys.h" |
|
|
#include "strings.h" |
|
|
|
|
|
#ifdef __BORLANDC__ |
|
|
# undef FILENAME |
|
|
#endif |
|
|
|
|
|
#define WIN32_LEAN_AND_MEAN |
|
|
#include <windows.h> |
|
|
|
|
|
#include <assert.h> |
|
|
#include <ctype.h> |
|
|
#include <direct.h> |
|
|
#include <io.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int file_collect_dir_content_( file_info_t * const d ) |
|
|
{ |
|
|
PATHNAME f; |
|
|
string pathspec[ 1 ]; |
|
|
string pathname[ 1 ]; |
|
|
LIST * files = L0; |
|
|
int d_length; |
|
|
|
|
|
assert( d ); |
|
|
assert( d->is_dir ); |
|
|
assert( list_empty( d->files ) ); |
|
|
|
|
|
d_length = strlen( object_str( d->name ) ); |
|
|
|
|
|
memset( (char *)&f, '\0', sizeof( f ) ); |
|
|
f.f_dir.ptr = object_str( d->name ); |
|
|
f.f_dir.len = d_length; |
|
|
|
|
|
|
|
|
if ( !d_length ) |
|
|
string_copy( pathspec, ".\\*" ); |
|
|
else |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char const trailingChar = object_str( d->name )[ d_length - 1 ] ; |
|
|
string_copy( pathspec, object_str( d->name ) ); |
|
|
if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) ) |
|
|
string_append( pathspec, "\\" ); |
|
|
string_append( pathspec, "*" ); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
WIN32_FIND_DATA finfo; |
|
|
HANDLE const findHandle = FindFirstFileA( pathspec->value, &finfo ); |
|
|
if ( findHandle == INVALID_HANDLE_VALUE ) |
|
|
{ |
|
|
string_free( pathspec ); |
|
|
return -1; |
|
|
} |
|
|
|
|
|
string_new( pathname ); |
|
|
do |
|
|
{ |
|
|
OBJECT * pathname_obj; |
|
|
|
|
|
f.f_base.ptr = finfo.cFileName; |
|
|
f.f_base.len = strlen( finfo.cFileName ); |
|
|
|
|
|
string_truncate( pathname, 0 ); |
|
|
path_build( &f, pathname ); |
|
|
|
|
|
pathname_obj = object_new( pathname->value ); |
|
|
path_register_key( pathname_obj ); |
|
|
files = list_push_back( files, pathname_obj ); |
|
|
{ |
|
|
int found; |
|
|
file_info_t * const ff = file_info( pathname_obj, &found ); |
|
|
ff->is_dir = finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; |
|
|
ff->is_file = !ff->is_dir; |
|
|
ff->exists = 1; |
|
|
timestamp_from_filetime( &ff->time, &finfo.ftLastWriteTime ); |
|
|
} |
|
|
} |
|
|
while ( FindNextFile( findHandle, &finfo ) ); |
|
|
|
|
|
FindClose( findHandle ); |
|
|
} |
|
|
|
|
|
string_free( pathname ); |
|
|
string_free( pathspec ); |
|
|
|
|
|
d->files = files; |
|
|
return 0; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void file_dirscan_( file_info_t * const d, scanback func, void * closure ) |
|
|
{ |
|
|
assert( d ); |
|
|
assert( d->is_dir ); |
|
|
|
|
|
|
|
|
{ |
|
|
char const * const name = object_str( d->name ); |
|
|
if ( name[ 0 ] == '\\' && !name[ 1 ] ) |
|
|
{ |
|
|
(*func)( closure, d->name, 1 , &d->time ); |
|
|
} |
|
|
else if ( name[ 0 ] && name[ 1 ] == ':' && name[ 2 ] && !name[ 3 ] ) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OBJECT * const dir_no_slash = object_new_range( name, 2 ); |
|
|
(*func)( closure, d->name, 1 , &d->time ); |
|
|
(*func)( closure, dir_no_slash, 1 , &d->time ); |
|
|
object_free( dir_no_slash ); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int file_mkdir( char const * const path ) |
|
|
{ |
|
|
return _mkdir( path ); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int try_file_query_root( file_info_t * const info ) |
|
|
{ |
|
|
WIN32_FILE_ATTRIBUTE_DATA fileData; |
|
|
char buf[ 4 ]; |
|
|
char const * const pathstr = object_str( info->name ); |
|
|
if ( !pathstr[ 0 ] ) |
|
|
{ |
|
|
buf[ 0 ] = '.'; |
|
|
buf[ 1 ] = 0; |
|
|
} |
|
|
else if ( pathstr[ 0 ] == '\\' && ! pathstr[ 1 ] ) |
|
|
{ |
|
|
buf[ 0 ] = '\\'; |
|
|
buf[ 1 ] = '\0'; |
|
|
} |
|
|
else if ( pathstr[ 1 ] == ':' ) |
|
|
{ |
|
|
if ( !pathstr[ 2 ] ) |
|
|
{ |
|
|
} |
|
|
else if ( !pathstr[ 2 ] || ( pathstr[ 2 ] == '\\' && !pathstr[ 3 ] ) ) |
|
|
{ |
|
|
buf[ 0 ] = pathstr[ 0 ]; |
|
|
buf[ 1 ] = ':'; |
|
|
buf[ 2 ] = '\\'; |
|
|
buf[ 3 ] = '\0'; |
|
|
} |
|
|
else |
|
|
{ |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
return 0; |
|
|
} |
|
|
|
|
|
|
|
|
if ( !GetFileAttributesExA( buf, GetFileExInfoStandard, &fileData ) ) |
|
|
{ |
|
|
info->is_dir = 0; |
|
|
info->is_file = 0; |
|
|
info->exists = 0; |
|
|
timestamp_clear( &info->time ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
info->is_dir = fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; |
|
|
info->is_file = !info->is_dir; |
|
|
info->exists = 1; |
|
|
timestamp_from_filetime( &info->time, &fileData.ftLastWriteTime ); |
|
|
} |
|
|
return 1; |
|
|
} |
|
|
|
|
|
void file_query_( file_info_t * const info ) |
|
|
{ |
|
|
char const * const pathstr = object_str( info->name ); |
|
|
const char * dir; |
|
|
OBJECT * parent; |
|
|
file_info_t * parent_info; |
|
|
|
|
|
if ( try_file_query_root( info ) ) |
|
|
return; |
|
|
|
|
|
if ( ( dir = strrchr( pathstr, '\\' ) ) ) |
|
|
{ |
|
|
parent = object_new_range( pathstr, dir - pathstr ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
parent = object_copy( constant_empty ); |
|
|
} |
|
|
parent_info = file_query( parent ); |
|
|
object_free( parent ); |
|
|
if ( !parent_info || !parent_info->is_dir ) |
|
|
{ |
|
|
info->is_dir = 0; |
|
|
info->is_file = 0; |
|
|
info->exists = 0; |
|
|
timestamp_clear( &info->time ); |
|
|
} |
|
|
else |
|
|
{ |
|
|
info->is_dir = 0; |
|
|
info->is_file = 0; |
|
|
info->exists = 0; |
|
|
timestamp_clear( &info->time ); |
|
|
if ( list_empty( parent_info->files ) ) |
|
|
file_collect_dir_content_( parent_info ); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void file_supported_fmt_resolution( timestamp * const t ) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
timestamp_init( t, 0, 0 ); |
|
|
} |
|
|
|
|
|
#endif |
|
|
|