2005-09-20 21:26:39 +08:00
|
|
|
/** \file wutil.c
|
2006-01-20 22:27:21 +08:00
|
|
|
Wide character equivalents of various standard unix
|
2006-03-02 00:53:47 +08:00
|
|
|
functions.
|
2005-09-20 21:26:39 +08: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 08:51:26 +08:00
|
|
|
#include <wctype.h>
|
2005-09-20 21:26:39 +08:00
|
|
|
#include <string.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <limits.h>
|
2006-06-14 21:22:40 +08:00
|
|
|
#include <libgen.h>
|
2012-02-18 07:55:54 +08:00
|
|
|
#include <pthread.h>
|
2011-12-27 11:18:46 +08:00
|
|
|
#include <string>
|
2012-02-25 04:13:35 +08:00
|
|
|
#include <map>
|
2005-09-20 21:26:39 +08:00
|
|
|
|
2012-02-18 07:55:54 +08:00
|
|
|
|
2006-07-20 06:55:49 +08:00
|
|
|
#if HAVE_LIBINTL_H
|
|
|
|
#include <libintl.h>
|
|
|
|
#endif
|
2006-02-28 21:17:16 +08:00
|
|
|
|
|
|
|
#include "fallback.h"
|
2005-09-20 21:26:39 +08:00
|
|
|
#include "util.h"
|
2006-02-28 21:17:16 +08:00
|
|
|
|
2005-09-20 21:26:39 +08:00
|
|
|
#include "common.h"
|
|
|
|
#include "wutil.h"
|
|
|
|
|
2011-12-27 11:18:46 +08:00
|
|
|
typedef std::string cstring;
|
|
|
|
|
2006-06-20 08:50:10 +08:00
|
|
|
/**
|
|
|
|
Minimum length of the internal covnersion buffers
|
|
|
|
*/
|
2005-11-02 23:41:59 +08:00
|
|
|
#define TMP_LEN_MIN 256
|
|
|
|
|
2006-02-02 23:23:56 +08:00
|
|
|
#ifndef PATH_MAX
|
|
|
|
#ifdef MAXPATHLEN
|
|
|
|
#define PATH_MAX MAXPATHLEN
|
|
|
|
#else
|
2006-06-20 08:50:10 +08:00
|
|
|
/**
|
|
|
|
Fallback length of MAXPATHLEN. Just a hopefully sane value...
|
|
|
|
*/
|
2006-02-02 23:23:56 +08:00
|
|
|
#define PATH_MAX 4096
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2006-07-20 06:55:49 +08:00
|
|
|
/**
|
|
|
|
For wgettext: Number of string_buffer_t in the ring of buffers
|
|
|
|
*/
|
2006-10-21 06:34:40 +08:00
|
|
|
#define BUFF_COUNT 4
|
2006-07-20 06:55:49 +08:00
|
|
|
|
2012-02-25 04:13:35 +08:00
|
|
|
/* Lock to protect wgettext */
|
|
|
|
static pthread_mutex_t wgettext_lock;
|
|
|
|
|
|
|
|
/* Maps string keys to (immortal) pointers to string values */
|
|
|
|
typedef std::map<wcstring, wcstring *> wgettext_map_t;
|
|
|
|
static std::map<wcstring, wcstring *> wgettext_map;
|
2006-07-20 06:55:49 +08:00
|
|
|
|
2005-11-02 23:41:59 +08:00
|
|
|
void wutil_init()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2005-09-20 21:26:39 +08:00
|
|
|
void wutil_destroy()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-03-02 16:27:40 +08:00
|
|
|
static pthread_mutex_t readdir_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
2012-02-20 18:13:31 +08:00
|
|
|
bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
struct dirent *d = readdir( dir );
|
2012-02-18 10:08:08 +08:00
|
|
|
if ( !d ) return false;
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2012-02-20 18:13:31 +08:00
|
|
|
out_name = str2wcstring(d->d_name);
|
|
|
|
if (out_is_dir) {
|
|
|
|
bool is_dir;
|
|
|
|
if (d->d_type == DT_DIR) {
|
|
|
|
is_dir = true;
|
|
|
|
} else if (d->d_type == DT_LNK) {
|
|
|
|
/* We want to treat symlinks to directories as directories. Use stat to resolve it. */
|
|
|
|
cstring fullpath = wcs2string(dir_path);
|
|
|
|
fullpath.push_back('/');
|
|
|
|
fullpath.append(d->d_name);
|
|
|
|
struct stat buf;
|
|
|
|
if (stat(fullpath.c_str(), &buf) != 0) {
|
|
|
|
is_dir = false;
|
|
|
|
} else {
|
|
|
|
is_dir = !! (S_ISDIR(buf.st_mode));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
is_dir = false;
|
|
|
|
}
|
|
|
|
*out_is_dir = is_dir;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool wreaddir(DIR *dir, std::wstring &out_name)
|
|
|
|
{
|
|
|
|
struct dirent *d = readdir( dir );
|
|
|
|
if ( !d ) return false;
|
|
|
|
|
|
|
|
out_name = str2wcstring(d->d_name);
|
2012-02-18 10:08:08 +08:00
|
|
|
return true;
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2006-02-08 22:58:47 +08:00
|
|
|
|
2005-09-20 21:26:39 +08:00
|
|
|
wchar_t *wgetcwd( wchar_t *buff, size_t sz )
|
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
char *buffc = (char *)malloc( sz*MAX_UTF8_BYTES);
|
2006-05-12 23:44:47 +08:00
|
|
|
char *res;
|
|
|
|
wchar_t *ret = 0;
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-05-12 23:44:47 +08:00
|
|
|
if( !buffc )
|
|
|
|
{
|
|
|
|
errno = ENOMEM;
|
2005-09-20 21:26:39 +08:00
|
|
|
return 0;
|
2006-05-12 23:44:47 +08:00
|
|
|
}
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-05-12 23:44:47 +08:00
|
|
|
res = getcwd( buffc, sz*MAX_UTF8_BYTES );
|
|
|
|
if( res )
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2006-05-12 23:44:47 +08:00
|
|
|
if( (size_t)-1 != mbstowcs( buff, buffc, sizeof( wchar_t ) * sz ) )
|
|
|
|
{
|
|
|
|
ret = buff;
|
2011-12-27 11:18:46 +08:00
|
|
|
}
|
2006-05-12 23:44:47 +08:00
|
|
|
}
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-05-12 23:44:47 +08:00
|
|
|
free( buffc );
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-05-12 23:44:47 +08:00
|
|
|
return ret;
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int wchdir( const wcstring &dir )
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(dir);
|
|
|
|
return chdir( tmp.c_str() );
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
FILE *wfopen(const wcstring &path, const char *mode)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2012-03-02 16:27:40 +08:00
|
|
|
int permissions = 0, options = 0;
|
|
|
|
switch (*mode++) {
|
|
|
|
case 'r':
|
|
|
|
permissions = O_RDONLY;
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
permissions = O_WRONLY;
|
|
|
|
options = O_CREAT | O_TRUNC;
|
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
permissions = O_WRONLY;
|
|
|
|
options = O_CREAT | O_APPEND;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errno = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Skip binary */
|
|
|
|
if (*mode == 'b')
|
|
|
|
mode++;
|
|
|
|
|
|
|
|
/* Consider append option */
|
|
|
|
if (*mode == '+')
|
|
|
|
permissions = O_RDWR;
|
|
|
|
|
|
|
|
int fd = wopen_cloexec(path, permissions | options, 0666);
|
|
|
|
if (fd < 0)
|
|
|
|
return NULL;
|
|
|
|
FILE *result = fdopen(fd, mode);
|
|
|
|
if (result == NULL)
|
|
|
|
close(fd);
|
|
|
|
return result;
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
FILE *wfreopen(const wcstring &path, const char *mode, FILE *stream)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(path);
|
|
|
|
return freopen(tmp.c_str(), mode, stream);
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-03-02 16:27:40 +08:00
|
|
|
bool set_cloexec(int fd) {
|
|
|
|
int flags = fcntl(fd, F_GETFD, 0);
|
|
|
|
if (flags < 0) {
|
|
|
|
return false;
|
|
|
|
} else if (flags & FD_CLOEXEC) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return fcntl(fd, F_SETFD, flags | FD_CLOEXEC) >= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int wopen_internal(const wcstring &pathname, int flags, mode_t mode, bool cloexec)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(pathname);
|
2012-03-02 16:27:40 +08:00
|
|
|
int fd = ::open(tmp.c_str(), flags, mode);
|
|
|
|
if (cloexec && fd >= 0 && ! set_cloexec(fd)) {
|
|
|
|
close(fd);
|
|
|
|
fd = -1;
|
2011-12-27 11:18:46 +08:00
|
|
|
}
|
2012-03-02 16:27:40 +08:00
|
|
|
return fd;
|
|
|
|
|
|
|
|
}
|
|
|
|
int wopen(const wcstring &pathname, int flags, mode_t mode)
|
|
|
|
{
|
|
|
|
// off the main thread, always use wopen_cloexec
|
|
|
|
ASSERT_IS_MAIN_THREAD();
|
|
|
|
return wopen_internal(pathname, flags, mode, false);
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-03-02 16:27:40 +08:00
|
|
|
int wopen_cloexec(const wcstring &pathname, int flags, mode_t mode)
|
|
|
|
{
|
|
|
|
return wopen_internal(pathname, flags, mode, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int wcreat(const wcstring &pathname, mode_t mode)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(pathname);
|
|
|
|
return creat(tmp.c_str(), mode);
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
DIR *wopendir(const wcstring &name)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(name);
|
|
|
|
return opendir(tmp.c_str());
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int wstat(const wcstring &file_name, struct stat *buf)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(file_name);
|
|
|
|
return stat(tmp.c_str(), buf);
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int lwstat(const wcstring &file_name, struct stat *buf)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 13:05:07 +08:00
|
|
|
// fprintf(stderr, "%s\n", __PRETTY_FUNCTION__);
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(file_name);
|
|
|
|
return lstat(tmp.c_str(), buf);
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int waccess(const wcstring &file_name, int mode)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(file_name);
|
|
|
|
return access(tmp.c_str(), mode);
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int wunlink(const wcstring &file_name)
|
2012-02-16 16:24:27 +08:00
|
|
|
{
|
|
|
|
cstring tmp = wcs2string(file_name);
|
|
|
|
return unlink(tmp.c_str());
|
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
void wperror(const wcstring &s)
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2006-06-21 17:54:30 +08:00
|
|
|
int e = errno;
|
2012-02-19 01:11:22 +08:00
|
|
|
if( !s.empty() )
|
2005-09-20 21:26:39 +08:00
|
|
|
{
|
2012-02-19 01:11:22 +08:00
|
|
|
fwprintf( stderr, L"%ls: ", s.c_str() );
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
2006-06-21 17:54:30 +08:00
|
|
|
fwprintf( stderr, L"%s\n", strerror( e ) );
|
2005-09-20 21:26:39 +08:00
|
|
|
}
|
|
|
|
|
2006-02-02 23:23:56 +08:00
|
|
|
#ifdef HAVE_REALPATH_NULL
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path)
|
2006-02-02 23:23:56 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(pathname);
|
|
|
|
char *narrow_res = realpath( tmp.c_str(), 0 );
|
|
|
|
wchar_t *res;
|
2006-02-02 23:23:56 +08:00
|
|
|
|
|
|
|
if( !narrow_res )
|
|
|
|
return 0;
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-02-02 23:23:56 +08:00
|
|
|
if( resolved_path )
|
|
|
|
{
|
|
|
|
wchar_t *tmp2 = str2wcs( narrow_res );
|
|
|
|
wcslcpy( resolved_path, tmp2, PATH_MAX );
|
|
|
|
free( tmp2 );
|
2011-12-27 11:18:46 +08:00
|
|
|
res = resolved_path;
|
2006-02-02 23:23:56 +08: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-27 11:18:46 +08:00
|
|
|
cstring tmp = wcs2string(pathname);
|
2006-07-21 09:08:31 +08:00
|
|
|
char narrow_buff[PATH_MAX];
|
2011-12-27 11:18:46 +08:00
|
|
|
char *narrow_res = realpath( tmp.c_str(), narrow_buff );
|
|
|
|
wchar_t *res;
|
2006-02-02 23:23:56 +08:00
|
|
|
|
|
|
|
if( !narrow_res )
|
|
|
|
return 0;
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-02-02 23:23:56 +08:00
|
|
|
if( resolved_path )
|
|
|
|
{
|
|
|
|
wchar_t *tmp2 = str2wcs( narrow_res );
|
|
|
|
wcslcpy( resolved_path, tmp2, PATH_MAX );
|
|
|
|
free( tmp2 );
|
2011-12-27 11:18:46 +08:00
|
|
|
res = resolved_path;
|
2006-02-02 23:23:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
res = str2wcs( narrow_res );
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2006-06-14 21:22:40 +08:00
|
|
|
|
|
|
|
|
2011-12-27 11:18:46 +08:00
|
|
|
wcstring wdirname( const wcstring &path )
|
2006-06-14 21:22:40 +08:00
|
|
|
{
|
2011-12-27 11: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 21:22:40 +08:00
|
|
|
}
|
|
|
|
|
2011-12-27 11:18:46 +08:00
|
|
|
wcstring wbasename( const wcstring &path )
|
2006-06-14 21:22:40 +08:00
|
|
|
{
|
2011-12-27 11: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 21:22:40 +08:00
|
|
|
}
|
|
|
|
|
2012-02-18 07:55:54 +08:00
|
|
|
/* Really init wgettext */
|
|
|
|
static void wgettext_really_init() {
|
2012-02-25 04:13:35 +08:00
|
|
|
pthread_mutex_init(&wgettext_lock, NULL);
|
2006-07-20 06:55:49 +08:00
|
|
|
bindtextdomain( PACKAGE_NAME, LOCALEDIR );
|
|
|
|
textdomain( PACKAGE_NAME );
|
|
|
|
}
|
|
|
|
|
2012-02-18 07:55:54 +08:00
|
|
|
/**
|
|
|
|
For wgettext: Internal init function. Automatically called when a translation is first requested.
|
|
|
|
*/
|
|
|
|
static void wgettext_init_if_necessary()
|
|
|
|
{
|
|
|
|
static pthread_once_t once = PTHREAD_ONCE_INIT;
|
|
|
|
pthread_once(&once, wgettext_really_init);
|
|
|
|
}
|
|
|
|
|
2006-07-20 06:55:49 +08:00
|
|
|
const wchar_t *wgettext( const wchar_t *in )
|
|
|
|
{
|
|
|
|
if( !in )
|
|
|
|
return in;
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2012-02-18 07:55:54 +08:00
|
|
|
wgettext_init_if_necessary();
|
2012-02-25 04:13:35 +08:00
|
|
|
|
|
|
|
wcstring key = in;
|
|
|
|
scoped_lock lock(wgettext_lock);
|
|
|
|
|
|
|
|
wcstring *& val = wgettext_map[key];
|
|
|
|
if (val == NULL) {
|
|
|
|
cstring mbs_in = wcs2string(key);
|
|
|
|
char *out = gettext(mbs_in.c_str());
|
|
|
|
val = new wcstring(format_string(L"%s", out));
|
|
|
|
}
|
|
|
|
return val->c_str();
|
2006-07-20 06:55:49 +08:00
|
|
|
}
|
|
|
|
|
2012-02-18 07:55:54 +08:00
|
|
|
wcstring wgettext2(const wcstring &in) {
|
|
|
|
wgettext_init_if_necessary();
|
|
|
|
std::string mbs_in = wcs2string(in);
|
|
|
|
char *out = gettext( mbs_in.c_str() );
|
|
|
|
wcstring result = format_string(L"%s", out);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
const wchar_t *wgetenv( const wcstring &name )
|
2006-08-11 22:55:28 +08:00
|
|
|
{
|
2012-02-10 11:26:44 +08:00
|
|
|
ASSERT_IS_MAIN_THREAD();
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring name_narrow = wcs2string(name);
|
|
|
|
char *res_narrow = getenv( name_narrow.c_str() );
|
2012-02-10 11:26:44 +08:00
|
|
|
static wcstring out;
|
2006-08-11 22:55:28 +08:00
|
|
|
|
|
|
|
if( !res_narrow )
|
|
|
|
return 0;
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2012-02-10 11:26:44 +08:00
|
|
|
out = format_string(L"%s", res_narrow);
|
|
|
|
return out.c_str();
|
2011-12-27 11:18:46 +08:00
|
|
|
|
2006-08-11 22:55:28 +08:00
|
|
|
}
|
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int wmkdir( const wcstring &name, int mode )
|
2006-09-08 22:11:28 +08:00
|
|
|
{
|
2011-12-27 11:18:46 +08:00
|
|
|
cstring name_narrow = wcs2string(name);
|
|
|
|
return mkdir( name_narrow.c_str(), mode );
|
2006-09-08 22:11:28 +08:00
|
|
|
}
|
2006-10-21 06:33:47 +08:00
|
|
|
|
2012-02-19 01:11:22 +08:00
|
|
|
int wrename( const wcstring &old, const wcstring &newv )
|
2006-10-21 06:33:47 +08:00
|
|
|
{
|
2011-12-27 11: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 06:33:47 +08:00
|
|
|
}
|