[PATCH 2 of 2] osutil.c added proper support for unicode
Petr Kodl
petrkodl at gmail.com
Thu Sep 4 11:27:47 CDT 2008
# HG changeset patch
# User Petr Kodl<petrkodl at gmail.com>
# Date 1220544667 14400
# Node ID bbfc523b12ff1a813dc0e3b687e76b93985b697e
# Parent e150128b40c0f80871799c2d8de3684d767729f2
osutil.c added proper support for unicode
diff -r e150128b40c0 -r bbfc523b12ff mercurial/osutil.c
--- a/mercurial/osutil.c Wed Sep 03 19:52:29 2008 -0400
+++ b/mercurial/osutil.c Thu Sep 04 12:11:07 2008 -0400
@@ -14,6 +14,7 @@
#ifdef _WIN32
#include <windows.h>
+#include <malloc.h> /* for _alloca */
#else
#include <dirent.h>
#include <fcntl.h>
@@ -131,113 +132,170 @@
};
#ifdef _WIN32
-
-static __int64 a0 = (__int64)134774L*(__int64)24L*(__int64)3600L*(__int64)1000L*(__int64)1000L*(__int64)10L;
-static __int64 a1 = 1000*1000*10;
static int to_python_time(FILETIME* ms_time)
{
+ static __int64 a0 = (__int64)134774L*(__int64)24L*(__int64)3600L*(__int64)1000L*(__int64)1000L*(__int64)10L;
+ static __int64 a1 = 1000*1000*10;
__int64 tmp;
memcpy(&tmp,ms_time,sizeof(__int64));
return (int)((tmp-a0)/a1);
}
+static int allow_unicode()
+{
+ static int allow = -1;
+ if(allow==-1) allow = (GetVersion() < 0x80000000) ? 1 : 0; /* unicode supported for NT */
+ return allow;
+}
+
static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
{
- static char *kwlist[] = { "path", "stat", NULL };
- PyObject *list = NULL;
- PyObject* item = NULL;
- PyObject *py_st = NULL;
- PyObject *statobj = NULL;
- PyObject *ctor_args = PyTuple_New(0);
- struct non_posix_stat* stp = 0;
- char *path;
- int path_len;
- int keep_stat;
- WIN32_FIND_DATA fd;
- HANDLE fh=NULL;
- char full_path[_MAX_PATH+10];
-
- if(!PyArg_ParseTupleAndKeywords(args,kwargs,"s#|O:listdir",kwlist,&path,&path_len,&statobj))
- goto end;
-
- keep_stat = statobj && PyObject_IsTrue(statobj);
-
- strncpy(full_path,path,path_len);
- strncpy(full_path+path_len,"\\*.*",5);
-
- fh = FindFirstFile(full_path,&fd);
- if(INVALID_HANDLE_VALUE!=fh)
+ PyObject *pathobj = NULL,
+ *statobj = NULL,
+ *list = NULL,
+ *items = NULL,
+ *ctor_args = NULL,
+ *item0 = NULL,
+ *item1 = NULL,
+ *py_st = NULL;
+ HANDLE fh = 0;
+ struct non_posix_stat* stp=0;
+ static char *kwlist[] = { "path", "stat", NULL };
+ if(PyArg_ParseTupleAndKeywords(args,kwargs,"O|O:listdir",kwlist,&pathobj,&statobj))
{
- list = PyList_New(0);
- if(!list)
+ int keepstat= statobj && PyObject_IsTrue(statobj);
+ int unicode = allow_unicode() && PyUnicode_CheckExact(pathobj);
+ WIN32_FIND_DATAA fd_a;
+ WIN32_FIND_DATAW fd_w;
+ if(unicode)
{
- PyErr_NoMemory();
- goto end;
+ Py_ssize_t len = PyUnicode_GET_SIZE(pathobj);
+ wchar_t *wpath = _alloca((len+5)*sizeof(wchar_t));
+ memset(wpath,0,(len+5)*sizeof(wchar_t));
+ if(PyUnicode_AsWideChar((PyUnicodeObject*)pathobj,wpath,len)!=len) return 0;
+ if(len>0 && wpath[len-1]!=L':' && wpath[len-1]!=L'/' && wpath[len-1]!='\\') wpath[len++]=L'\\';
+ wcscpy(wpath+len,L"*.*");
+ fh = FindFirstFileW(wpath,&fd_w);
}
- do
+ else if(PyString_CheckExact(pathobj))
{
- int isdir = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
- int isro = (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
- if(!isdir || (strcmp(fd.cFileName,".") && strcmp(fd.cFileName,"..") ))
+ Py_ssize_t len = PyString_GET_SIZE(pathobj);
+ char path[_MAX_PATH];
+ strncpy(path,PyString_AS_STRING(pathobj),_MAX_PATH);
+ if(len>0 && path[len-1]!=':' && path[len-1]!='/' && path[len-1]!='\\') path[len++]='\\';
+ strcpy(path+len,"*.*");
+ fh = FindFirstFileA(path,&fd_a);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_TypeError,"listdir - expected string or unicode as first argument");
+ goto error;
+ }
+ if(INVALID_HANDLE_VALUE!=fh)
+ {
+ list = PyList_New(0);
+ ctor_args = PyTuple_New(0);
+ if(!list || !ctor_args)
{
- PyObject* item = PyTuple_New(keep_stat ? 3 : 2);
- if(!item)
+ PyErr_NoMemory();
+ goto error;
+ }
+ do
+ {
+ #define FD(NAME) (unicode ? fd_w.NAME : fd_a.NAME)
+ int isdir = (FD(dwFileAttributes) & FILE_ATTRIBUTE_DIRECTORY);
+ int isro = (FD(dwFileAttributes) & FILE_ATTRIBUTE_READONLY);
+ if( !isdir
+ || (unicode && wcscmp(fd_w.cFileName,L".") && wcscmp(fd_w.cFileName,L".."))
+ || (!unicode&& strcmp(fd_a.cFileName,".") && strcmp(fd_a.cFileName,"..")))
{
- PyErr_NoMemory();
- goto end;
+ items = PyTuple_New(keepstat ? 3 : 2);
+ item0 = unicode ? PyUnicode_FromWideChar(fd_w.cFileName,wcslen(fd_w.cFileName)) : PyString_FromString(fd_a.cFileName);
+ item1 = PyInt_FromLong(isdir ? _S_IFDIR : _S_IFREG);
+ if(!items || !item0 || !item1)
+ {
+ PyErr_NoMemory();
+ goto error;
+ }
+ PyTuple_SetItem(items,0,item0);
+ PyTuple_SetItem(items,1,item1);
+ item0 = item1 = 0;
+ if(keepstat)
+ {
+ py_st = PyObject_CallObject((PyObject *)&listdir_stat_type,ctor_args);
+ if(!py_st)
+ {
+ PyErr_NoMemory();
+ goto error;
+ }
+ stp = &((struct listdir_stat *)py_st)->st;
+ stp->st_mtime = to_python_time(unicode ? &fd_w.ftLastWriteTime : &fd_a.ftLastWriteTime);
+ stp->st_ctime = to_python_time(unicode ? &fd_w.ftCreationTime : &fd_a.ftLastWriteTime);
+ stp->st_dev = 0;
+ stp->st_size = 0;
+ stp->st_mode = (isdir ? (S_IFDIR | 0111) : S_IFREG) | (isro ? 0444 : 0666);
+ if(!isdir)
+ {
+ stp->st_size = (__int64)(FD(nFileSizeHigh)<<32) + FD(nFileSizeLow);
+ if(!unicode)
+ {
+ char* dot = strrchr(fd_a.cFileName,'.');
+ if (dot)
+ {
+ if( !stricmp(dot,".bat")
+ || !stricmp(dot,".cmd")
+ || !stricmp(dot,".exe")
+ || !stricmp(dot,".com"))
+ stp->st_mode |= 0111;
+ }
+ }
+ else
+ {
+ wchar_t* dot = wcsrchr(fd_w.cFileName,L'.');
+ if (dot)
+ {
+ if( !_wcsicmp(dot,L".bat")
+ || !_wcsicmp(dot,L".cmd")
+ || !_wcsicmp(dot,L".exe")
+ || !_wcsicmp(dot,L".com"))
+ stp->st_mode |= 0111;
+ }
+ }
+ }
+ PyTuple_SET_ITEM(items,2,py_st); py_st = 0;
+ }
+ if(-1==PyList_Append(list,items))
+ {
+ goto error;
+ }
+ Py_XDECREF(items); items = 0;
}
- PyTuple_SetItem(item,0,PyString_FromString(fd.cFileName));
- PyTuple_SetItem(item,1,PyInt_FromLong(isdir ? _S_IFDIR : _S_IFREG));
- if(keep_stat)
- {
- py_st = PyObject_CallObject((PyObject *)&listdir_stat_type,ctor_args);
- if(!py_st)
- {
- PyErr_NoMemory();
- goto end;
- }
- stp = &((struct listdir_stat *)py_st)->st;
- stp->st_mtime = to_python_time(&fd.ftLastWriteTime);
- stp->st_ctime = to_python_time(&fd.ftCreationTime);
- stp->st_dev = 0;
- stp->st_size = 0;
- stp->st_mode = (isdir ? (S_IFDIR | 0111) : S_IFREG) | (isro ? 0444 : 0666);
- if(!isdir)
- {
- char* dot = strrchr(fd.cFileName,'.');
- if (dot)
- {
- if( !stricmp(dot,".bat")
- || !stricmp(dot,".cmd")
- || !stricmp(dot,".exe")
- || !stricmp(dot,".com"))
- stp->st_mode |= 0111;
- }
- stp->st_size = (__int64)(fd.nFileSizeHigh<<32) + fd.nFileSizeLow;
- }
- PyTuple_SetItem(item,2,py_st);
- py_st = NULL;
- }
- PyList_Append(list,item);
- Py_XDECREF(item);
- item=NULL;
+ #undef FD
}
+ while(unicode ? FindNextFileW(fh,&fd_w) : FindNextFileA(fh,&fd_a));
+ Py_XDECREF(ctor_args); ctor_args=0;
+ if(GetLastError()!=ERROR_NO_MORE_FILES || !FindClose(fh))
+ {
+ PyErr_SetExcFromWindowsErr(PyExc_OSError,GetLastError());
+ goto error;
+ }
+ fh = 0;
+ PyList_Sort(list);
+ return list;
}
- while(FindNextFile(fh,&fd));
- FindClose(fh);
+ else
+ PyErr_SetExcFromWindowsErr(PyExc_OSError,GetLastError());
}
- else
- {
- PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError,GetLastError(),path);
- }
-end:
+error:
+ Py_XDECREF(list);
Py_XDECREF(ctor_args);
- Py_XDECREF(item);
- Py_XDECREF(py_st);
- if(list) PyList_Sort(list);
- return list;
-}
+ Py_XDECREF(items);
+ Py_XDECREF(item0);
+ Py_XDECREF(item1);
+ if(fh) FindClose(fh);
+ return 0;
+}
#else
More information about the Mercurial-devel
mailing list