bpo-41142: Add support of non-ASCII paths for CAB files. (GH-21195)
* The path to the CAB file can be non-ASCII. * Paths of added files can be non-ASCII.
This commit is contained in:
parent
694d31e714
commit
ba67d7386e
|
@ -112,6 +112,16 @@ class MsiDatabaseTestCase(unittest.TestCase):
|
||||||
with self.assertRaises(msilib.MSIError):
|
with self.assertRaises(msilib.MSIError):
|
||||||
si.GetProperty(-1)
|
si.GetProperty(-1)
|
||||||
|
|
||||||
|
def test_FCICreate(self):
|
||||||
|
filepath = TESTFN + '.txt'
|
||||||
|
cabpath = TESTFN + '.cab'
|
||||||
|
self.addCleanup(unlink, filepath)
|
||||||
|
with open(filepath, 'wb'):
|
||||||
|
pass
|
||||||
|
self.addCleanup(unlink, cabpath)
|
||||||
|
msilib.FCICreate(cabpath, [(filepath, 'test.txt')])
|
||||||
|
self.assertTrue(os.path.isfile(cabpath))
|
||||||
|
|
||||||
|
|
||||||
class Test_make_id(unittest.TestCase):
|
class Test_make_id(unittest.TestCase):
|
||||||
#http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx
|
#http://msdn.microsoft.com/en-us/library/aa369212(v=vs.85).aspx
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
:mod:`msilib` now supports creating CAB files with non-ASCII file path and
|
||||||
|
adding files with non-ASCII file path to them.
|
67
PC/_msi.c
67
PC/_msi.c
|
@ -41,21 +41,50 @@ uuidcreate(PyObject* obj, PyObject*args)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper for converting file names from UTF-8 to wchat_t*. */
|
||||||
|
static wchar_t *
|
||||||
|
utf8_to_wchar(const char *s, int *err)
|
||||||
|
{
|
||||||
|
PyObject *obj = PyUnicode_FromString(s);
|
||||||
|
if (obj == NULL) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||||
|
*err = ENOMEM;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*err = EINVAL;
|
||||||
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wchar_t *ws = PyUnicode_AsWideCharString(obj, NULL);
|
||||||
|
if (ws == NULL) {
|
||||||
|
*err = ENOMEM;
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
Py_DECREF(obj);
|
||||||
|
return ws;
|
||||||
|
}
|
||||||
|
|
||||||
/* FCI callback functions */
|
/* FCI callback functions */
|
||||||
|
|
||||||
static FNFCIALLOC(cb_alloc)
|
static FNFCIALLOC(cb_alloc)
|
||||||
{
|
{
|
||||||
return malloc(cb);
|
return PyMem_RawMalloc(cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FNFCIFREE(cb_free)
|
static FNFCIFREE(cb_free)
|
||||||
{
|
{
|
||||||
free(memory);
|
PyMem_RawFree(memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FNFCIOPEN(cb_open)
|
static FNFCIOPEN(cb_open)
|
||||||
{
|
{
|
||||||
int result = _open(pszFile, oflag | O_NOINHERIT, pmode);
|
wchar_t *ws = utf8_to_wchar(pszFile, err);
|
||||||
|
if (ws == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int result = _wopen(ws, oflag | O_NOINHERIT, pmode);
|
||||||
|
PyMem_Free(ws);
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
*err = errno;
|
*err = errno;
|
||||||
return result;
|
return result;
|
||||||
|
@ -95,7 +124,12 @@ static FNFCISEEK(cb_seek)
|
||||||
|
|
||||||
static FNFCIDELETE(cb_delete)
|
static FNFCIDELETE(cb_delete)
|
||||||
{
|
{
|
||||||
int result = remove(pszFile);
|
wchar_t *ws = utf8_to_wchar(pszFile, err);
|
||||||
|
if (ws == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int result = _wremove(ws);
|
||||||
|
PyMem_Free(ws);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
*err = errno;
|
*err = errno;
|
||||||
return result;
|
return result;
|
||||||
|
@ -159,15 +193,22 @@ static FNFCIGETOPENINFO(cb_getopeninfo)
|
||||||
FILETIME filetime;
|
FILETIME filetime;
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
|
|
||||||
/* Need Win32 handle to get time stamps */
|
wchar_t *ws = utf8_to_wchar(pszName, err);
|
||||||
handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
if (ws == NULL) {
|
||||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (handle == INVALID_HANDLE_VALUE)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (GetFileInformationByHandle(handle, &bhfi) == FALSE)
|
/* Need Win32 handle to get time stamps */
|
||||||
{
|
handle = CreateFileW(ws, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||||
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (handle == INVALID_HANDLE_VALUE) {
|
||||||
|
PyMem_Free(ws);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetFileInformationByHandle(handle, &bhfi) == FALSE) {
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
PyMem_Free(ws);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +220,9 @@ static FNFCIGETOPENINFO(cb_getopeninfo)
|
||||||
|
|
||||||
CloseHandle(handle);
|
CloseHandle(handle);
|
||||||
|
|
||||||
return _open(pszName, _O_RDONLY | _O_BINARY | O_NOINHERIT);
|
int result = _wopen(ws, _O_RDONLY | _O_BINARY | O_NOINHERIT);
|
||||||
|
PyMem_Free(ws);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject* fcicreate(PyObject* obj, PyObject* args)
|
static PyObject* fcicreate(PyObject* obj, PyObject* args)
|
||||||
|
@ -212,7 +255,7 @@ static PyObject* fcicreate(PyObject* obj, PyObject* args)
|
||||||
ccab.setID = 0;
|
ccab.setID = 0;
|
||||||
ccab.szDisk[0] = '\0';
|
ccab.szDisk[0] = '\0';
|
||||||
|
|
||||||
for (i = 0, p = cabname; *p; p = CharNext(p))
|
for (i = 0, p = cabname; *p; p++)
|
||||||
if (*p == '\\' || *p == '/')
|
if (*p == '\\' || *p == '/')
|
||||||
i = p - cabname + 1;
|
i = p - cabname + 1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue