static rc_t transform_to_utf8_and_make_vpath ( const VFSManager * self, VPath ** new_path, const wchar_t * src, bool dos_path ) { rc_t rc = 0; size_t src_size, dst_size; uint32_t len = wchar_cvt_string_measure ( src, & src_size, & dst_size ); if ( len == 0 ) rc = RC ( rcVFS, rcMgr, rcConstructing, rcPath, rcEmpty ); else { /* transform to UTF-8 */ size_t copy_size; char utf8_path [ 4096 ], *dst = utf8_path; if ( dst_size < sizeof utf8_path ) dst_size = sizeof utf8_path; else { dst = malloc ( ++ dst_size ); if ( dst == NULL ) return RC ( rcVFS, rcMgr, rcConstructing, rcMemory, rcExhausted ); } copy_size = wchar_cvt_string_copy ( dst, dst_size, src, src_size ); if ( copy_size >= dst_size ) rc = RC ( rcVFS, rcMgr, rcConstructing, rcBuffer, rcInsufficient ); else { size_t i = 0; dst [ copy_size ] = 0; /* encode drive letter */ if ( dos_path ) { assert ( isalpha ( dst [ 0 ] ) ); assert ( dst [ 1 ] == ':' ); dst [ 1 ] = dst [ 0 ]; dst [ 0 ] = '/'; i = 2; } /* convert '\\' to '/' */ for ( ; i < copy_size; ++ i ) { if ( dst [ i ] == '\\' ) dst [ i ] = '/'; } /* this is the final goal! */ rc = VFSManagerMakePath ( self, new_path, "%.*s", ( uint32_t ) copy_size, dst ); } if ( dst != utf8_path ) free ( dst ); } return rc; }
static bool CC list_dylib ( void *item, void *data ) { size_t bytes; char utf8 [ 4096 ], *p; list_dylib_param *pb = data; const KDylib *lib = ( const void* ) item; /* "lib" was created with KDylibMake which creates a NUL terminated path. of course, this could seg-fault if bad... */ assert ( lib -> path . addr [ lib -> path . len ] == 0 ); /* convert wide-character to UTF-8 */ bytes = wchar_cvt_string_copy ( utf8, sizeof utf8, lib -> path . addr, lib -> path . size ); if ( bytes < sizeof utf8 ) { pb -> rc = VNamelistAppend ( pb -> list, utf8 ); return pb -> rc != 0; } p = malloc ( 16 * 1024 ); if ( p == NULL ) { pb -> rc = RC ( rcFS, rcDylib, rcListing, rcMemory, rcExhausted ); return true; } bytes = wchar_cvt_string_copy ( p, 16 * 1024, lib -> path . addr, lib -> path . size ); if ( bytes >= 16 * 1024 ) pb -> rc = RC ( rcFS, rcDylib, rcListing, rcPath, rcTooLong ); else pb -> rc = VNamelistAppend ( pb -> list, p ); free ( p ); return pb -> rc != 0; }
/* FullPath * return full path to library */ LIB_EXPORT rc_t CC KDylibFullPath ( const KDylib *self, char *path, size_t psize ) { rc_t rc; if ( psize == 0 ) rc = RC ( rcFS, rcDylib, rcAccessing, rcBuffer, rcInsufficient ); else if ( path == NULL ) rc = RC ( rcFS, rcDylib, rcAccessing, rcBuffer, rcNull ); else { if ( self == NULL ) rc = RC ( rcFS, rcDylib, rcAccessing, rcSelf, rcNull ); else { size_t i, bytes = wchar_cvt_string_copy ( path, psize, self -> path . addr, self -> path . size ); if ( bytes < psize ) { if ( isalpha ( path [ 0 ] ) && path [ 1 ] == ':' ) { path [ 1 ] = path [ 0 ]; path [ 0 ] = '/'; } for ( i = 0; i < bytes; ++ i ) { if ( path [ i ] == '\\' ) path [ i ] = '/'; } return 0; } rc = RC ( rcFS, rcDylib, rcAccessing, rcBuffer, rcInsufficient ); } path [ 0 ] = 0; } return rc; }
static char *rewrite_arg ( const wchar_t *arg ) { char *utf8; bool has_drive = false; size_t i, src_size, dst_size; DWORD len; /* detect drive or full path */ wchar_t rewrit [ MAX_PATH ]; if ( arg [ 0 ] < 128 ) { bool rewrite = false; /* look for non-drive path */ if ( arg [ 0 ] == '\\' || arg [ 0 ] == '/' ) { /* full path - not network */ if ( arg [ 1 ] != '\\' && arg [ 1 ] != '/' ) { /* check for cygdrive */ if ( memcmp( arg, L"/cygdrive/", sizeof L"/cygdrive/" - sizeof L"" ) == 0 ) arg += sizeof "/cygdrive" - 1; else rewrite = true; } } /* look for drive path */ else if ( isalpha ( arg [ 0 ] ) && arg [ 1 ] == ':' ) { has_drive = true; /* look for drive relative */ if ( arg [ 2 ] != '\\' && arg [ 2 ] != '/' ) rewrite = true; } if ( rewrite ) { /* incomplete path */ len = GetFullPathNameW ( arg, sizeof rewrit / sizeof rewrit [ 0 ], rewrit, NULL ); if ( len == 0 || len >= MAX_PATH ) { /* complain */ return NULL; } arg = rewrit; has_drive = ( isalpha ( arg [ 0 ] ) && arg [ 1 ] == ':' ); } } /* this point, we should only have normal arguments, or network/full/drive-full/relative paths */ /* measure the string */ len = wchar_cvt_string_measure ( arg, & src_size, & dst_size ); /* allocate a UTF-8 buffer */ utf8 = malloc ( dst_size + 1 ); if ( utf8 != NULL ) { /* normal arguments get no offsets */ uint32_t offset = 0; /* check for need to convert drive */ if ( has_drive ) { /* convert to pseudo mount point */ utf8 [ 0 ] = '/'; utf8 [ 1 ] = ( char ) arg [ 0 ]; offset = 2; } /* copy the wide argument to utf8 */ wchar_cvt_string_copy ( & utf8 [ offset ], dst_size - offset + 1, & arg [ offset ], src_size - offset * sizeof * arg ); /* terminate the string */ utf8 [ dst_size ] = 0; /* map all backslashes to fwdslashes */ for ( i = 0; i < dst_size; ++ i ) { if ( utf8 [ i ] == '\\' ) utf8 [ i ] = '/'; } } return utf8; }