Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 84972) +++ Modules/posixmodule.c (working copy) @@ -1125,6 +1125,74 @@ return has_GetFinalPathNameByHandle; } +static char * +get_final_path_name_by_handle_a(HANDLE hFile) +{ + int buf_size; + char *target_path; + int result_length; + + assert(hFile != INVALID_HANDLE_VALUE); + + buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS); + if (!buf_size) + return NULL; + /* On some platforms, GetFinalPathNameByHandle may return not the + required buffer size but the length of string. So we need to + allocate one more room for null terminator. */ + buf_size++; + + target_path = (char *)malloc(buf_size * sizeof(char)); + if (!target_path) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + result_length = Py_GetFinalPathNameByHandleA(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + if (!result_length) { + free(target_path); + return NULL; + } + +/* target_path[result_length] = 0; */ /* XXX: Is this needed? */ + return target_path; +} + +static wchar_t * +get_final_path_name_by_handle_w(HANDLE hFile) +{ + int buf_size; + wchar_t *target_path; + int result_length; + + assert(hFile != INVALID_HANDLE_VALUE); + + buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_DOS); + if (!buf_size) + return NULL; + /* On some platforms, GetFinalPathNameByHandle may return not the + required buffer size but the length of string. So we need to + allocate one more room for null terminator. */ + buf_size++; + + target_path = (wchar_t *)malloc(buf_size * sizeof(wchar_t)); + if (!target_path) { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, + buf_size, VOLUME_NAME_DOS); + if (!result_length) { + free(target_path); + return NULL; + } + +/* target_path[result_length] = 0; */ /* XXX: Is this needed? */ + return target_path; +} + static int win32_stat(const char* path, struct win32_stat *result) { @@ -1133,12 +1201,10 @@ */ int code; HANDLE hFile; - int buf_size; char *target_path; - int result_length; WIN32_FILE_ATTRIBUTE_DATA info; - - if(!check_GetFinalPathNameByHandle()) { + + if (!check_GetFinalPathNameByHandle()) { /* if the OS doesn't have GetFinalPathNameByHandle, it doesn't have symlinks, so just fall back to the traditional behavior found in lstat. */ @@ -1154,8 +1220,8 @@ /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL); - - if(hFile == INVALID_HANDLE_VALUE) { + + if (hFile == INVALID_HANDLE_VALUE) { /* Either the target doesn't exist, or we don't have access to get a handle to it. If the former, we need to return an error. If the latter, we can use attributes_from_dir. */ @@ -1178,30 +1244,19 @@ else { /* We have a good handle to the target, use it to determine the target path name (then we'll call lstat on it). */ - buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS); - if(!buf_size) return -1; - /* Due to a slight discrepancy between GetFinalPathNameByHandleA - and GetFinalPathNameByHandleW, we must allocate one more byte - than reported. */ - target_path = (char *)malloc((buf_size+2)*sizeof(char)); - result_length = Py_GetFinalPathNameByHandleA(hFile, target_path, - buf_size+1, VOLUME_NAME_DOS); - - if(!result_length) { - free(target_path); + target_path = get_final_path_name_by_handle_a(hFile); + if (!target_path) { + CloseHandle(hFile); return -1; } - - if(!CloseHandle(hFile)) { + if (!CloseHandle(hFile)) { free(target_path); return -1; } - - target_path[result_length] = 0; code = win32_lstat(target_path, result); free(target_path); } - + return code; } @@ -1211,12 +1266,10 @@ /* Traverse the symlink to the target using GetFinalPathNameByHandle() */ int code; HANDLE hFile; - int buf_size; wchar_t *target_path; - int result_length; WIN32_FILE_ATTRIBUTE_DATA info; - - if(!check_GetFinalPathNameByHandle()) { + + if (!check_GetFinalPathNameByHandle()) { /* If the OS doesn't have GetFinalPathNameByHandle, it doesn't have symlinks, so just fall back to the traditional behavior found in lstat. */ @@ -1233,7 +1286,7 @@ FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL); - if(hFile == INVALID_HANDLE_VALUE) { + if (hFile == INVALID_HANDLE_VALUE) { /* Either the target doesn't exist, or we don't have access to get a handle to it. If the former, we need to return an error. If the latter, we can use attributes_from_dir. */ @@ -1256,29 +1309,19 @@ else { /* We have a good handle to the target, use it to determine the target path name (then we'll call lstat on it). */ - buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_DOS); - if(!buf_size) + target_path = get_final_path_name_by_handle_w(hFile); + if (!target_path) { + CloseHandle(hFile); return -1; - - target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t)); - result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, - buf_size, VOLUME_NAME_DOS); - - if(!result_length) { - free(target_path); - return -1; } - - if(!CloseHandle(hFile)) { + if (!CloseHandle(hFile)) { free(target_path); return -1; } - - target_path[result_length] = 0; code = win32_lstat_w(target_path, result); free(target_path); } - + return code; } @@ -2647,17 +2690,15 @@ posix__getfinalpathname(PyObject *self, PyObject *args) { HANDLE hFile; - int buf_size; wchar_t *target_path; - int result_length; PyObject *result; wchar_t *path; - + if (!PyArg_ParseTuple(args, "u|:_getfullpathname", &path)) { return NULL; } - if(!check_GetFinalPathNameByHandle()) { + if (!check_GetFinalPathNameByHandle()) { /* If the OS doesn't have GetFinalPathNameByHandle, return a NotImplementedError. */ return PyErr_Format(PyExc_NotImplementedError, @@ -2673,34 +2714,22 @@ /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ FILE_FLAG_BACKUP_SEMANTICS, NULL); - - if(hFile == INVALID_HANDLE_VALUE) { + + if (hFile == INVALID_HANDLE_VALUE) return win32_error_unicode("GetFinalPathNamyByHandle", path); - return PyErr_Format(PyExc_RuntimeError, - "Could not get a handle to file."); - } /* We have a good handle to the target, use it to determine the target path name. */ - buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); - - if(!buf_size) + target_path = get_final_path_name_by_handle_w(hFile); + if (!target_path) { + CloseHandle(hFile); return win32_error_unicode("GetFinalPathNameByHandle", path); - - target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t)); - if(!target_path) - return PyErr_NoMemory(); - - result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, - buf_size, VOLUME_NAME_DOS); - if(!result_length) - return win32_error_unicode("GetFinalPathNamyByHandle", path); - - if(!CloseHandle(hFile)) + } + if (!CloseHandle(hFile)) { + free(target_path); return win32_error_unicode("GetFinalPathNameByHandle", path); - - target_path[result_length] = 0; - result = PyUnicode_FromUnicode(target_path, result_length); + } + result = PyUnicode_FromUnicode(target_path, wcslen(target_path)); free(target_path); return result;