2005-09-20 23:26:39 +10:00
/** \file wutil.c
2006-01-21 00:27:21 +10:00
Wide character equivalents of various standard unix
2006-03-02 02:53:47 +10:00
functions .
2005-09-20 23:26:39 +10:00
*/
# include "config.h"
# include <stdlib.h>
# include <stdio.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <errno.h>
# include <fcntl.h>
# include <wchar.h>
2005-10-15 10:51:26 +10:00
# include <wctype.h>
2005-09-20 23:26:39 +10:00
# include <string.h>
# include <dirent.h>
# include <stdarg.h>
# include <limits.h>
2006-06-14 23:22:40 +10:00
# include <libgen.h>
2011-12-26 19:18:46 -08:00
# include <string>
2005-09-20 23:26:39 +10:00
2006-07-20 08:55:49 +10:00
# if HAVE_LIBINTL_H
# include <libintl.h>
# endif
2006-02-28 23:17:16 +10:00
# include "fallback.h"
2005-09-20 23:26:39 +10:00
# include "util.h"
2006-02-28 23:17:16 +10:00
2005-09-20 23:26:39 +10:00
# include "common.h"
# include "wutil.h"
2011-12-26 19:18:46 -08:00
typedef std : : string cstring ;
2006-06-20 10:50:10 +10:00
/**
Minimum length of the internal covnersion buffers
*/
2005-11-03 01:41:59 +10:00
# define TMP_LEN_MIN 256
2006-02-03 01:23:56 +10:00
# ifndef PATH_MAX
# ifdef MAXPATHLEN
# define PATH_MAX MAXPATHLEN
# else
2006-06-20 10:50:10 +10:00
/**
Fallback length of MAXPATHLEN . Just a hopefully sane value . . .
*/
2006-02-03 01:23:56 +10:00
# define PATH_MAX 4096
# endif
# endif
2006-07-20 08:55:49 +10:00
/**
For wgettext : Number of string_buffer_t in the ring of buffers
*/
2006-10-21 08:34:40 +10:00
# define BUFF_COUNT 4
2006-07-20 08:55:49 +10:00
/**
For wgettext : The ring of string_buffer_t
*/
static string_buffer_t buff [ BUFF_COUNT ] ;
/**
For wgettext : Current position in the ring
*/
static int curr_buff = 0 ;
/**
For wgettext : Buffer used by translate_wcs2str
*/
static char * wcs2str_buff = 0 ;
/**
For wgettext : Size of buffer used by translate_wcs2str
*/
static size_t wcs2str_buff_count = 0 ;
/**
For wgettext : Flag to tell whether the translation library has been initialized
*/
static int wgettext_is_init = 0 ;
2005-11-03 01:41:59 +10:00
void wutil_init ( )
{
}
2005-09-20 23:26:39 +10:00
void wutil_destroy ( )
{
}
2011-12-26 19:18:46 -08:00
std : : wstring * wreaddir ( DIR * dir , std : : wstring & outPath )
2005-09-20 23:26:39 +10:00
{
2011-12-26 19:18:46 -08:00
struct dirent * d = readdir ( dir ) ;
if ( ! d ) return 0 ;
outPath = str2wcstring ( d - > d_name ) ;
return & outPath ;
2005-09-20 23:26:39 +10:00
}
2006-02-09 00:58:47 +10:00
2005-09-20 23:26:39 +10:00
wchar_t * wgetcwd ( wchar_t * buff , size_t sz )
{
2011-12-26 19:18:46 -08:00
char * buffc = ( char * ) malloc ( sz * MAX_UTF8_BYTES ) ;
2006-05-13 01:44:47 +10:00
char * res ;
wchar_t * ret = 0 ;
2011-12-26 19:18:46 -08:00
2006-05-13 01:44:47 +10:00
if ( ! buffc )
{
errno = ENOMEM ;
2005-09-20 23:26:39 +10:00
return 0 ;
2006-05-13 01:44:47 +10:00
}
2011-12-26 19:18:46 -08:00
2006-05-13 01:44:47 +10:00
res = getcwd ( buffc , sz * MAX_UTF8_BYTES ) ;
if ( res )
2005-09-20 23:26:39 +10:00
{
2006-05-13 01:44:47 +10:00
if ( ( size_t ) - 1 ! = mbstowcs ( buff , buffc , sizeof ( wchar_t ) * sz ) )
{
ret = buff ;
2011-12-26 19:18:46 -08:00
}
2006-05-13 01:44:47 +10:00
}
2011-12-26 19:18:46 -08:00
2006-05-13 01:44:47 +10:00
free ( buffc ) ;
2011-12-26 19:18:46 -08:00
2006-05-13 01:44:47 +10:00
return ret ;
2005-09-20 23:26:39 +10:00
}
int wchdir ( const wchar_t * dir )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( dir ) ;
return chdir ( tmp . c_str ( ) ) ;
2005-09-20 23:26:39 +10:00
}
FILE * wfopen ( const wchar_t * path , const char * mode )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( path ) ;
return fopen ( tmp . c_str ( ) , mode ) ;
2005-09-20 23:26:39 +10:00
}
FILE * wfreopen ( const wchar_t * path , const char * mode , FILE * stream )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( path ) ;
return freopen ( tmp . c_str ( ) , mode , stream ) ;
2005-09-20 23:26:39 +10:00
}
int wopen ( const wchar_t * pathname , int flags , . . . )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( pathname ) ;
2005-09-20 23:26:39 +10:00
int res = - 1 ;
2011-12-26 19:18:46 -08:00
va_list argp ;
if ( ! ( flags & O_CREAT ) )
{
res = open ( tmp . c_str ( ) , flags ) ;
}
else
{
va_start ( argp , flags ) ;
res = open ( tmp . c_str ( ) , flags , va_arg ( argp , int ) ) ;
va_end ( argp ) ;
}
2005-09-20 23:26:39 +10:00
return res ;
}
int wcreat ( const wchar_t * pathname , mode_t mode )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( pathname ) ;
return creat ( tmp . c_str ( ) , mode ) ;
2005-09-20 23:26:39 +10:00
}
DIR * wopendir ( const wchar_t * name )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( name ) ;
return opendir ( tmp . c_str ( ) ) ;
2005-09-20 23:26:39 +10:00
}
int wstat ( const wchar_t * file_name , struct stat * buf )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( file_name ) ;
return stat ( tmp . c_str ( ) , buf ) ;
2005-09-20 23:26:39 +10:00
}
int lwstat ( const wchar_t * file_name , struct stat * buf )
{
2011-12-26 21:05:07 -08:00
// fprintf(stderr, "%s\n", __PRETTY_FUNCTION__);
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( file_name ) ;
return lstat ( tmp . c_str ( ) , buf ) ;
2005-09-20 23:26:39 +10:00
}
int waccess ( const wchar_t * file_name , int mode )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( file_name ) ;
return access ( tmp . c_str ( ) , mode ) ;
2005-09-20 23:26:39 +10:00
}
2012-02-16 00:24:27 -08:00
int wunlink ( const wchar_t * file_name )
{
cstring tmp = wcs2string ( file_name ) ;
return unlink ( tmp . c_str ( ) ) ;
}
2005-09-20 23:26:39 +10:00
void wperror ( const wchar_t * s )
{
2006-06-21 19:54:30 +10:00
int e = errno ;
2005-09-20 23:26:39 +10:00
if ( s ! = 0 )
{
fwprintf ( stderr , L " %ls: " , s ) ;
}
2006-06-21 19:54:30 +10:00
fwprintf ( stderr , L " %s \n " , strerror ( e ) ) ;
2005-09-20 23:26:39 +10:00
}
2006-02-03 01:23:56 +10:00
# ifdef HAVE_REALPATH_NULL
wchar_t * wrealpath ( const wchar_t * pathname , wchar_t * resolved_path )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( pathname ) ;
char * narrow_res = realpath ( tmp . c_str ( ) , 0 ) ;
wchar_t * res ;
2006-02-03 01:23:56 +10:00
if ( ! narrow_res )
return 0 ;
2011-12-26 19:18:46 -08:00
2006-02-03 01:23:56 +10:00
if ( resolved_path )
{
wchar_t * tmp2 = str2wcs ( narrow_res ) ;
wcslcpy ( resolved_path , tmp2 , PATH_MAX ) ;
free ( tmp2 ) ;
2011-12-26 19:18:46 -08:00
res = resolved_path ;
2006-02-03 01:23:56 +10:00
}
else
{
res = str2wcs ( narrow_res ) ;
}
free ( narrow_res ) ;
return res ;
}
# else
wchar_t * wrealpath ( const wchar_t * pathname , wchar_t * resolved_path )
{
2011-12-26 19:18:46 -08:00
cstring tmp = wcs2string ( pathname ) ;
2006-07-21 11:08:31 +10:00
char narrow_buff [ PATH_MAX ] ;
2011-12-26 19:18:46 -08:00
char * narrow_res = realpath ( tmp . c_str ( ) , narrow_buff ) ;
wchar_t * res ;
2006-02-03 01:23:56 +10:00
if ( ! narrow_res )
return 0 ;
2011-12-26 19:18:46 -08:00
2006-02-03 01:23:56 +10:00
if ( resolved_path )
{
wchar_t * tmp2 = str2wcs ( narrow_res ) ;
wcslcpy ( resolved_path , tmp2 , PATH_MAX ) ;
free ( tmp2 ) ;
2011-12-26 19:18:46 -08:00
res = resolved_path ;
2006-02-03 01:23:56 +10:00
}
else
{
res = str2wcs ( narrow_res ) ;
}
return res ;
}
# endif
2006-06-14 23:22:40 +10:00
2011-12-26 19:18:46 -08:00
wcstring wdirname ( const wcstring & path )
2006-06-14 23:22:40 +10:00
{
2011-12-26 19:18:46 -08:00
char * tmp = wcs2str ( path . c_str ( ) ) ;
char * narrow_res = dirname ( tmp ) ;
wcstring result = format_string ( L " %s " , narrow_res ) ;
free ( tmp ) ;
return result ;
2006-06-14 23:22:40 +10:00
}
2011-12-26 19:18:46 -08:00
wcstring wbasename ( const wcstring & path )
2006-06-14 23:22:40 +10:00
{
2011-12-26 19:18:46 -08:00
char * tmp = wcs2str ( path . c_str ( ) ) ;
char * narrow_res = basename ( tmp ) ;
wcstring result = format_string ( L " %s " , narrow_res ) ;
free ( tmp ) ;
return result ;
2006-06-14 23:22:40 +10:00
}
2006-07-20 08:55:49 +10:00
/**
For wgettext : Internal init function . Automatically called when a translation is first requested .
*/
static void wgettext_init ( )
{
int i ;
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
wgettext_is_init = 1 ;
2011-12-26 19:18:46 -08:00
2006-07-21 11:08:31 +10:00
for ( i = 0 ; i < BUFF_COUNT ; i + + )
2006-07-20 08:55:49 +10:00
{
sb_init ( & buff [ i ] ) ;
}
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
bindtextdomain ( PACKAGE_NAME , LOCALEDIR ) ;
textdomain ( PACKAGE_NAME ) ;
}
/**
For wgettext : Wide to narrow character conversion . Internal implementation that
avoids exessive calls to malloc
*/
static char * wgettext_wcs2str ( const wchar_t * in )
{
size_t len = MAX_UTF8_BYTES * wcslen ( in ) + 1 ;
if ( len > wcs2str_buff_count )
{
2011-12-26 19:18:46 -08:00
wcs2str_buff = ( char * ) realloc ( wcs2str_buff , len ) ;
2006-07-20 08:55:49 +10:00
if ( ! wcs2str_buff )
{
DIE_MEM ( ) ;
}
}
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
return wcs2str_internal ( in , wcs2str_buff ) ;
}
const wchar_t * wgettext ( const wchar_t * in )
{
if ( ! in )
return in ;
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
if ( ! wgettext_is_init )
wgettext_init ( ) ;
2011-12-26 19:18:46 -08:00
char * mbs_in = wgettext_wcs2str ( in ) ;
2006-07-20 08:55:49 +10:00
char * out = gettext ( mbs_in ) ;
wchar_t * wres = 0 ;
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
sb_clear ( & buff [ curr_buff ] ) ;
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
sb_printf ( & buff [ curr_buff ] , L " %s " , out ) ;
wres = ( wchar_t * ) buff [ curr_buff ] . buff ;
curr_buff = ( curr_buff + 1 ) % BUFF_COUNT ;
2011-12-26 19:18:46 -08:00
2006-07-20 08:55:49 +10:00
return wres ;
}
2012-02-09 19:26:44 -08:00
const wchar_t * wgetenv ( const wchar_t * name )
2006-08-12 00:55:28 +10:00
{
2012-02-09 19:26:44 -08:00
ASSERT_IS_MAIN_THREAD ( ) ;
2011-12-26 19:18:46 -08:00
cstring name_narrow = wcs2string ( name ) ;
char * res_narrow = getenv ( name_narrow . c_str ( ) ) ;
2012-02-09 19:26:44 -08:00
static wcstring out ;
2006-08-12 00:55:28 +10:00
if ( ! res_narrow )
return 0 ;
2011-12-26 19:18:46 -08:00
2012-02-09 19:26:44 -08:00
out = format_string ( L " %s " , res_narrow ) ;
return out . c_str ( ) ;
2011-12-26 19:18:46 -08:00
2006-08-12 00:55:28 +10:00
}
2006-09-09 00:11:28 +10:00
int wmkdir ( const wchar_t * name , int mode )
{
2011-12-26 19:18:46 -08:00
cstring name_narrow = wcs2string ( name ) ;
return mkdir ( name_narrow . c_str ( ) , mode ) ;
2006-09-09 00:11:28 +10:00
}
2006-10-21 08:33:47 +10:00
2011-12-26 19:18:46 -08:00
int wrename ( const wchar_t * old , const wchar_t * newv )
2006-10-21 08:33:47 +10:00
{
2011-12-26 19:18:46 -08:00
cstring old_narrow = wcs2string ( old ) ;
cstring new_narrow = wcs2string ( newv ) ;
return rename ( old_narrow . c_str ( ) , new_narrow . c_str ( ) ) ;
2006-10-21 08:33:47 +10:00
}