summaryrefslogtreecommitdiffstats
path: root/win/tclWinFile.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tclWinFile.c')
-rwxr-xr-x[-rw-r--r--]win/tclWinFile.c467
1 files changed, 280 insertions, 187 deletions
diff --git a/win/tclWinFile.c b/win/tclWinFile.c
index 6582ee1..fa5f28e 100644..100755
--- a/win/tclWinFile.c
+++ b/win/tclWinFile.c
@@ -156,27 +156,27 @@ static void FromCTime(time_t posixTime, FILETIME *fileTime);
* Declarations for local functions defined in this file:
*/
-static int NativeAccess(const TCHAR *path, int mode);
-static int NativeDev(const TCHAR *path);
-static int NativeStat(const TCHAR *path, Tcl_StatBuf *statPtr,
+static int NativeAccess(const WCHAR *path, int mode);
+static int NativeDev(const WCHAR *path);
+static int NativeStat(const WCHAR *path, Tcl_StatBuf *statPtr,
int checkLinks);
static unsigned short NativeStatMode(DWORD attr, int checkLinks,
int isExec);
-static int NativeIsExec(const TCHAR *path);
-static int NativeReadReparse(const TCHAR *LinkDirectory,
+static int NativeIsExec(const WCHAR *path);
+static int NativeReadReparse(const WCHAR *LinkDirectory,
REPARSE_DATA_BUFFER *buffer, DWORD desiredAccess);
-static int NativeWriteReparse(const TCHAR *LinkDirectory,
+static int NativeWriteReparse(const WCHAR *LinkDirectory,
REPARSE_DATA_BUFFER *buffer);
static int NativeMatchType(int isDrive, DWORD attr,
- const TCHAR *nativeName, Tcl_GlobTypeData *types);
+ const WCHAR *nativeName, Tcl_GlobTypeData *types);
static int WinIsDrive(const char *name, size_t nameLen);
static int WinIsReserved(const char *path);
-static Tcl_Obj * WinReadLink(const TCHAR *LinkSource);
-static Tcl_Obj * WinReadLinkDirectory(const TCHAR *LinkDirectory);
-static int WinLink(const TCHAR *LinkSource,
- const TCHAR *LinkTarget, int linkAction);
-static int WinSymLinkDirectory(const TCHAR *LinkDirectory,
- const TCHAR *LinkTarget);
+static Tcl_Obj * WinReadLink(const WCHAR *LinkSource);
+static Tcl_Obj * WinReadLinkDirectory(const WCHAR *LinkDirectory);
+static int WinLink(const WCHAR *LinkSource,
+ const WCHAR *LinkTarget, int linkAction);
+static int WinSymLinkDirectory(const WCHAR *LinkDirectory,
+ const WCHAR *LinkTarget);
MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...);
/*
@@ -191,12 +191,12 @@ MODULE_SCOPE TCL_NORETURN void tclWinDebugPanic(const char *format, ...);
static int
WinLink(
- const TCHAR *linkSourcePath,
- const TCHAR *linkTargetPath,
+ const WCHAR *linkSourcePath,
+ const WCHAR *linkTargetPath,
int linkAction)
{
- TCHAR tempFileName[MAX_PATH];
- TCHAR *tempFilePart;
+ WCHAR tempFileName[MAX_PATH];
+ WCHAR *tempFilePart;
DWORD attr;
/*
@@ -306,10 +306,10 @@ WinLink(
static Tcl_Obj *
WinReadLink(
- const TCHAR *linkSourcePath)
+ const WCHAR *linkSourcePath)
{
- TCHAR tempFileName[MAX_PATH];
- TCHAR *tempFilePart;
+ WCHAR tempFileName[MAX_PATH];
+ WCHAR *tempFilePart;
DWORD attr;
/*
@@ -370,8 +370,8 @@ WinReadLink(
static int
WinSymLinkDirectory(
- const TCHAR *linkDirPath,
- const TCHAR *linkTargetPath)
+ const WCHAR *linkDirPath,
+ const WCHAR *linkTargetPath)
{
DUMMY_REPARSE_BUFFER dummy;
REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy;
@@ -442,8 +442,8 @@ WinSymLinkDirectory(
int
TclWinSymLinkCopyDirectory(
- const TCHAR *linkOrigPath, /* Existing junction - reparse point */
- const TCHAR *linkCopyPath) /* Will become a duplicate junction */
+ const WCHAR *linkOrigPath, /* Existing junction - reparse point */
+ const WCHAR *linkCopyPath) /* Will become a duplicate junction */
{
DUMMY_REPARSE_BUFFER dummy;
REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER *) &dummy;
@@ -473,7 +473,7 @@ TclWinSymLinkCopyDirectory(
int
TclWinSymLinkDelete(
- const TCHAR *linkOrigPath,
+ const WCHAR *linkOrigPath,
int linkOnly)
{
/*
@@ -538,7 +538,7 @@ TclWinSymLinkDelete(
static Tcl_Obj *
WinReadLinkDirectory(
- const TCHAR *linkDirPath)
+ const WCHAR *linkDirPath)
{
int attr, len, offset;
DUMMY_REPARSE_BUFFER dummy;
@@ -634,9 +634,9 @@ WinReadLinkDirectory(
}
}
- Tcl_WinTCharToUtf((const TCHAR *)
+ Tcl_WinTCharToUtf(
reparseBuffer->MountPointReparseBuffer.PathBuffer,
- (int) reparseBuffer->MountPointReparseBuffer
+ reparseBuffer->MountPointReparseBuffer
.SubstituteNameLength, &ds);
copy = Tcl_DStringValue(&ds)+offset;
@@ -673,14 +673,15 @@ WinReadLinkDirectory(
static int
NativeReadReparse(
- const TCHAR *linkDirPath, /* The junction to read */
+ const WCHAR *linkDirPath, /* The junction to read */
REPARSE_DATA_BUFFER *buffer,/* Pointer to buffer. Cannot be NULL */
DWORD desiredAccess)
{
HANDLE hFile;
DWORD returnedLength;
- hFile = CreateFile(linkDirPath, desiredAccess, FILE_SHARE_READ, NULL, OPEN_EXISTING,
+ hFile = CreateFile(linkDirPath, desiredAccess, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING,
FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
@@ -729,7 +730,7 @@ NativeReadReparse(
static int
NativeWriteReparse(
- const TCHAR *linkDirPath,
+ const WCHAR *linkDirPath,
REPARSE_DATA_BUFFER *buffer)
{
HANDLE hFile;
@@ -842,7 +843,7 @@ tclWinDebugPanic(
#endif
abort();
}
-
+
/*
*---------------------------------------------------------------------------
*
@@ -913,7 +914,7 @@ TclpMatchInDirectory(
* May be NULL. In particular the directory
* flag is very important. */
{
- const TCHAR *native;
+ const WCHAR *native;
if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) {
/*
@@ -931,9 +932,10 @@ TclpMatchInDirectory(
* Match a single file directly.
*/
+ int len;
DWORD attr;
WIN32_FILE_ATTRIBUTE_DATA data;
- const char *str = TclGetString(norm);
+ const char *str = TclGetStringFromObj(norm, &len);
native = Tcl_FSGetNativePath(pathPtr);
@@ -943,7 +945,7 @@ TclpMatchInDirectory(
}
attr = data.dwFileAttributes;
- if (NativeMatchType(WinIsDrive(str,norm->length), attr, native, types)) {
+ if (NativeMatchType(WinIsDrive(str,len), attr, native, types)) {
Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
}
}
@@ -954,7 +956,7 @@ TclpMatchInDirectory(
WIN32_FIND_DATA data;
const char *dirName; /* UTF-8 dir name, later with pattern
* appended. */
- size_t dirLength;
+ int dirLength;
int matchSpecialDots;
Tcl_DString ds; /* Native encoding of dir, also used
* temporarily for other things. */
@@ -993,8 +995,7 @@ TclpMatchInDirectory(
*/
Tcl_DStringInit(&dsOrig);
- dirName = TclGetString(fileNamePtr);
- dirLength = fileNamePtr->length;
+ dirName = TclGetStringFromObj(fileNamePtr, &dirLength);
Tcl_DStringAppend(&dsOrig, dirName, dirLength);
lastChar = dirName[dirLength -1];
@@ -1313,7 +1314,7 @@ NativeMatchType(
int isDrive, /* Is this a drive. */
DWORD attr, /* We already know the attributes for the
* file. */
- const TCHAR *nativeName, /* Native path to check. */
+ const WCHAR *nativeName, /* Native path to check. */
Tcl_GlobTypeData *types) /* Type description to match against. */
{
/*
@@ -1450,11 +1451,16 @@ TclpGetUserHome(
if (domain == NULL) {
const char *ptr;
- /* no domain - firstly check it's the current user */
- if ( (ptr = TclpGetUserName(&ds)) != NULL
- && strcasecmp(name, ptr) == 0
- ) {
- /* try safest and fastest way to get current user home */
+ /*
+ * No domain. Firstly check it's the current user
+ */
+
+ ptr = TclpGetUserName(&ds);
+ if (ptr != NULL && strcasecmp(name, ptr) == 0) {
+ /*
+ * Try safest and fastest way to get current user home
+ */
+
ptr = TclGetEnv("HOME", &ds);
if (ptr != NULL) {
Tcl_JoinPath(1, &ptr, bufferPtr);
@@ -1465,46 +1471,63 @@ TclpGetUserHome(
Tcl_DStringFree(&ds);
} else {
Tcl_DStringInit(&ds);
- wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds);
+ wName = TclUtfToWCharDString(domain + 1, -1, &ds);
rc = NetGetDCName(NULL, wName, (LPBYTE *) &wDomain);
Tcl_DStringFree(&ds);
nameLen = domain - name;
}
if (rc == 0) {
Tcl_DStringInit(&ds);
- wName = Tcl_UtfToUniCharDString(name, nameLen, &ds);
+ wName = TclUtfToWCharDString(name, nameLen, &ds);
while (NetUserGetInfo(wDomain, wName, 1, (LPBYTE *) &uiPtr) != 0) {
/*
- * user does not exists - if domain was not specified,
- * try again using current domain.
+ * User does not exist; if domain was not specified, try again
+ * using current domain.
*/
+
rc = 1;
- if (domain != NULL) break;
- /* get current domain */
+ if (domain != NULL) {
+ break;
+ }
+
+ /*
+ * Get current domain
+ */
+
rc = NetGetDCName(NULL, NULL, (LPBYTE *) &wDomain);
- if (rc != 0) break;
+ if (rc != 0) {
+ break;
+ }
domain = INT2PTR(-1); /* repeat once */
}
if (rc == 0) {
DWORD i, size = MAX_PATH;
+
wHomeDir = uiPtr->usri1_home_dir;
if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) {
size = lstrlenW(wHomeDir);
- Tcl_UniCharToUtfDString(wHomeDir, size, bufferPtr);
+ TclWCharToUtfDString(wHomeDir, size, bufferPtr);
} else {
/*
* User exists but has no home dir. Return
* "{GetProfilesDirectory}/<user>".
*/
+
GetProfilesDirectoryW(buf, &size);
- Tcl_UniCharToUtfDString(buf, size-1, bufferPtr);
+ TclWCharToUtfDString(buf, size-1, bufferPtr);
Tcl_DStringAppend(bufferPtr, "/", 1);
Tcl_DStringAppend(bufferPtr, name, nameLen);
}
result = Tcl_DStringValue(bufferPtr);
- /* be sure we returns normalized path */
- for (i = 0; i < size; ++i){
- if (result[i] == '\\') result[i] = '/';
+
+ /*
+ * Be sure we return normalized path
+ */
+
+ for (i = 0; i < size; ++i) {
+ if (result[i] == '\\') {
+ result[i] = '/';
+ }
}
NetApiBufferFree((void *) uiPtr);
}
@@ -1562,7 +1585,7 @@ TclpGetUserHome(
static int
NativeAccess(
- const TCHAR *nativePath, /* Path of file to access, native encoding. */
+ const WCHAR *nativePath, /* Path of file to access, native encoding. */
int mode) /* Permission setting. */
{
DWORD attr;
@@ -1592,48 +1615,72 @@ NativeAccess(
/*
* If it's not a directory (assume file), do several fast checks:
*/
+
if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
/*
* If the attributes say this is not writable at all. The file is a
* regular file (i.e., not a directory), then the file is not
- * writable, full stop. For directories, the read-only bit is
+ * writable, full stop. For directories, the read-only bit is
* (mostly) ignored by Windows, so we can't ascertain anything about
* directory access from the attrib data. However, if we have the
- * advanced 'getFileSecurityProc', then more robust ACL checks
- * will be done below.
+ * advanced 'getFileSecurityProc', then more robust ACL checks will be
+ * done below.
*/
+
if ((mode & W_OK) && (attr & FILE_ATTRIBUTE_READONLY)) {
Tcl_SetErrno(EACCES);
return -1;
}
- /* If doesn't have the correct extension, it can't be executable */
+ /*
+ * If doesn't have the correct extension, it can't be executable
+ */
+
if ((mode & X_OK) && !NativeIsExec(nativePath)) {
Tcl_SetErrno(EACCES);
return -1;
}
- /* Special case for read/write/executable check on file */
+
+ /*
+ * Special case for read/write/executable check on file
+ */
+
if ((mode & (R_OK|W_OK|X_OK)) && !(mode & ~(R_OK|W_OK|X_OK))) {
DWORD mask = 0;
HANDLE hFile;
- if (mode & R_OK) { mask |= GENERIC_READ; }
- if (mode & W_OK) { mask |= GENERIC_WRITE; }
- if (mode & X_OK) { mask |= GENERIC_EXECUTE; }
+
+ if (mode & R_OK) {
+ mask |= GENERIC_READ;
+ }
+ if (mode & W_OK) {
+ mask |= GENERIC_WRITE;
+ }
+ if (mode & X_OK) {
+ mask |= GENERIC_EXECUTE;
+ }
hFile = CreateFile(nativePath, mask,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
- OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile);
return 0;
}
- /* fast exit if access was denied */
+
+ /*
+ * Fast exit if access was denied
+ */
+
if (GetLastError() == ERROR_ACCESS_DENIED) {
Tcl_SetErrno(EACCES);
return -1;
}
}
- /* We cannnot verify the access fast, check it below using security info. */
+
+ /*
+ * We cannnot verify the access fast, check it below using security
+ * info.
+ */
}
/*
@@ -1824,9 +1871,9 @@ NativeAccess(
static int
NativeIsExec(
- const TCHAR *path)
+ const WCHAR *path)
{
- int len = _tcslen(path);
+ int len = wcslen(path);
if (len < 5) {
return 0;
@@ -1837,11 +1884,11 @@ NativeIsExec(
}
path += len-3;
- if ((_tcsicmp(path, TEXT("exe")) == 0)
- || (_tcsicmp(path, TEXT("com")) == 0)
- || (_tcsicmp(path, TEXT("cmd")) == 0)
- || (_tcsicmp(path, TEXT("cmd")) == 0)
- || (_tcsicmp(path, TEXT("bat")) == 0)) {
+ if ((wcsicmp(path, L"exe") == 0)
+ || (wcsicmp(path, L"com") == 0)
+ || (wcsicmp(path, L"cmd") == 0)
+ || (wcsicmp(path, L"cmd") == 0)
+ || (wcsicmp(path, L"bat") == 0)) {
return 1;
}
return 0;
@@ -1868,7 +1915,7 @@ TclpObjChdir(
Tcl_Obj *pathPtr) /* Path to new working directory. */
{
int result;
- const TCHAR *nativePath;
+ const WCHAR *nativePath;
nativePath = Tcl_FSGetNativePath(pathPtr);
@@ -1912,7 +1959,7 @@ TclpGetCwd(
Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
* name of current directory. */
{
- TCHAR buffer[MAX_PATH];
+ WCHAR buffer[MAX_PATH];
char *p;
WCHAR *native;
@@ -1935,7 +1982,7 @@ TclpGetCwd(
&& (native[2] == '\\') && (native[3] == '\\')) {
native += 2;
}
- Tcl_WinTCharToUtf((TCHAR *) native, -1, bufferPtr);
+ Tcl_WinTCharToUtf(native, -1, bufferPtr);
/*
* Convert to forward slashes for easier use in scripts.
@@ -1990,7 +2037,7 @@ TclpObjStat(
static int
NativeStat(
- const TCHAR *nativePath, /* Path of file to stat */
+ const WCHAR *nativePath, /* Path of file to stat */
Tcl_StatBuf *statPtr, /* Filled with results of stat call. */
int checkLinks) /* If non-zero, behave like 'lstat' */
{
@@ -2008,13 +2055,12 @@ NativeStat(
* 'getFileAttributesExProc', and if that isn't available, then on even
* simpler routines.
*
- * Special consideration must be given to Windows hardcoded names
- * like CON, NULL, COM1, LPT1 etc. For these, we still need to
- * do the CreateFile as some may not exist (e.g. there is no CON
- * in wish by default). However the subsequent GetFileInformationByHandle
- * will fail. We do a WinIsReserved to see if it is one of the special
- * names, and if successful, mock up a BY_HANDLE_FILE_INFORMATION
- * structure.
+ * Special consideration must be given to Windows hardcoded names like
+ * CON, NULL, COM1, LPT1 etc. For these, we still need to do the
+ * CreateFile as some may not exist (e.g. there is no CON in wish by
+ * default). However the subsequent GetFileInformationByHandle will
+ * fail. We do a WinIsReserved to see if it is one of the special names,
+ * and if successful, mock up a BY_HANDLE_FILE_INFORMATION structure.
*/
fileHandle = CreateFile(nativePath, GENERIC_READ,
@@ -2032,7 +2078,11 @@ NativeStat(
Tcl_SetErrno(ENOENT);
return -1;
}
- /* Mock up the expected structure */
+
+ /*
+ * Mock up the expected structure
+ */
+
memset(&data, 0, sizeof(data));
statPtr->st_atime = 0;
statPtr->st_mtime = 0;
@@ -2131,12 +2181,12 @@ NativeStat(
static int
NativeDev(
- const TCHAR *nativePath) /* Full path of file to stat */
+ const WCHAR *nativePath) /* Full path of file to stat */
{
int dev;
Tcl_DString ds;
- TCHAR nativeFullPath[MAX_PATH];
- TCHAR *nativePart;
+ WCHAR nativeFullPath[MAX_PATH];
+ WCHAR *nativePart;
const char *fullPath;
GetFullPathName(nativePath, MAX_PATH, nativeFullPath, &nativePart);
@@ -2145,7 +2195,7 @@ NativeDev(
if ((fullPath[0] == '\\') && (fullPath[1] == '\\')) {
const char *p;
DWORD dw;
- const TCHAR *nativeVol;
+ const WCHAR *nativeVol;
Tcl_DString volString;
p = strchr(fullPath + 2, '\\');
@@ -2307,7 +2357,7 @@ ClientData
TclpGetNativeCwd(
ClientData clientData)
{
- TCHAR buffer[MAX_PATH];
+ WCHAR buffer[MAX_PATH];
if (GetCurrentDirectory(MAX_PATH, buffer) == 0) {
TclWinConvertError(GetLastError());
@@ -2315,7 +2365,7 @@ TclpGetNativeCwd(
}
if (clientData != NULL) {
- if (_tcscmp((const TCHAR*)clientData, buffer) == 0) {
+ if (wcscmp((const WCHAR *) clientData, buffer) == 0) {
return clientData;
}
}
@@ -2356,8 +2406,8 @@ TclpObjLink(
{
if (toPtr != NULL) {
int res;
- const TCHAR *LinkTarget;
- const TCHAR *LinkSource = Tcl_FSGetNativePath(pathPtr);
+ const WCHAR *LinkTarget;
+ const WCHAR *LinkSource = Tcl_FSGetNativePath(pathPtr);
Tcl_Obj *normalizedToPtr = Tcl_FSGetNormalizedPath(NULL, toPtr);
if (normalizedToPtr == NULL) {
@@ -2376,7 +2426,7 @@ TclpObjLink(
return NULL;
}
} else {
- const TCHAR *LinkSource = Tcl_FSGetNativePath(pathPtr);
+ const WCHAR *LinkSource = Tcl_FSGetNativePath(pathPtr);
if (LinkSource == NULL) {
return NULL;
@@ -2410,7 +2460,7 @@ TclpFilesystemPathType(
{
#define VOL_BUF_SIZE 32
int found;
- TCHAR volType[VOL_BUF_SIZE];
+ WCHAR volType[VOL_BUF_SIZE];
char *firstSeparator;
const char *path;
Tcl_Obj *normPath = Tcl_FSGetNormalizedPath(NULL, pathPtr);
@@ -2511,7 +2561,7 @@ TclpObjNormalizePath(
*/
WIN32_FILE_ATTRIBUTE_DATA data;
- const TCHAR *nativePath = Tcl_WinUtfToTChar(path,
+ const WCHAR *nativePath = Tcl_WinUtfToTChar(path,
currentPathEndPosition - path, &ds);
if (GetFileAttributesEx(nativePath,
@@ -2543,10 +2593,12 @@ TclpObjNormalizePath(
(int)(sizeof(WCHAR) * len));
lastValidPathEnd = currentPathEndPosition;
} else if (nextCheckpoint == 0) {
- /* Path starts with a drive designation
- * that's not actually on the system.
- * We still must normalize up past the
- * first separator. [Bug 3603434] */
+ /*
+ * Path starts with a drive designation that's not
+ * actually on the system. We still must normalize up
+ * past the first separator. [Bug 3603434]
+ */
+
currentPathEndPosition++;
}
}
@@ -2561,11 +2613,10 @@ TclpObjNormalizePath(
*/
/*
- * Check for symlinks, except at last component of path (we
- * don't follow final symlinks). Also a drive (C:/) for
- * example, may sometimes have the reparse flag set for some
- * reason I don't understand. We therefore don't perform this
- * check for drives.
+ * Check for symlinks, except at last component of path (we don't
+ * follow final symlinks). Also a drive (C:/) for example, may
+ * sometimes have the reparse flag set for some reason I don't
+ * understand. We therefore don't perform this check for drives.
*/
if (cur != 0 && !isDrive &&
@@ -2574,8 +2625,8 @@ TclpObjNormalizePath(
if (to != NULL) {
/*
- * Read the reparse point ok. Now, reparse points need
- * not be normalized, otherwise we could use:
+ * Read the reparse point ok. Now, reparse points need not
+ * be normalized, otherwise we could use:
*
* Tcl_GetStringFromObj(to, &pathLen);
* nextCheckpoint = pathLen;
@@ -2615,9 +2666,9 @@ TclpObjNormalizePath(
#ifndef TclNORM_LONG_PATH
/*
- * Now we convert the tail of the current path to its 'long
- * form', and append it to 'dsNorm' which holds the current
- * normalized path
+ * Now we convert the tail of the current path to its 'long form',
+ * and append it to 'dsNorm' which holds the current normalized
+ * path
*/
if (isDrive) {
@@ -2646,16 +2697,16 @@ TclpObjNormalizePath(
int dotLen = currentPathEndPosition-lastValidPathEnd;
/*
- * Path is just dots. We shouldn't really ever see a
- * path like that. However, to be nice we at least
- * don't mangle the path - we just add the dots as a
- * path segment and continue.
+ * Path is just dots. We shouldn't really ever see a path
+ * like that. However, to be nice we at least don't mangle
+ * the path - we just add the dots as a path segment and
+ * continue.
*/
Tcl_DStringAppend(&dsNorm, ((const char *)nativePath)
+ Tcl_DStringLength(&ds)
- - (dotLen * sizeof(TCHAR)),
- (int)(dotLen * sizeof(TCHAR)));
+ - (dotLen * sizeof(WCHAR)),
+ dotLen * sizeof(WCHAR));
} else {
/*
* Normal path.
@@ -2667,8 +2718,7 @@ TclpObjNormalizePath(
handle = FindFirstFileW((WCHAR *) nativePath, &fData);
if (handle == INVALID_HANDLE_VALUE) {
/*
- * This is usually the '/' in 'c:/' at end of
- * string.
+ * This is usually the '/' in 'c:/' at end of string.
*/
Tcl_DStringAppend(&dsNorm, (const char *) L"/",
@@ -2698,8 +2748,8 @@ TclpObjNormalizePath(
}
/*
- * If we get here, we've got past one directory delimiter, so
- * we know it is no longer a drive.
+ * If we get here, we've got past one directory delimiter, so we
+ * know it is no longer a drive.
*/
isDrive = 0;
@@ -2713,10 +2763,10 @@ TclpObjNormalizePath(
if (1) {
WCHAR wpath[MAX_PATH];
- const TCHAR *nativePath =
+ const WCHAR *nativePath =
Tcl_WinUtfToTChar(path, lastValidPathEnd - path, &ds);
DWORD wpathlen = GetLongPathNameProc(nativePath,
- (TCHAR *) wpath, MAX_PATH);
+ (WCHAR *) wpath, MAX_PATH);
/*
* We have to make the drive letter uppercase.
@@ -2744,7 +2794,7 @@ TclpObjNormalizePath(
* native encoding, so we have to convert it to Utf.
*/
- Tcl_WinTCharToUtf((const TCHAR *) Tcl_DStringValue(&dsNorm),
+ Tcl_WinTCharToUtf((const WCHAR *) Tcl_DStringValue(&dsNorm),
Tcl_DStringLength(&dsNorm), &ds);
nextCheckpoint = Tcl_DStringLength(&ds);
if (*lastValidPathEnd != 0) {
@@ -2752,14 +2802,15 @@ TclpObjNormalizePath(
* Not the end of the string.
*/
+ int len;
char *path;
Tcl_Obj *tmpPathPtr;
tmpPathPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
nextCheckpoint);
Tcl_AppendToObj(tmpPathPtr, lastValidPathEnd, -1);
- path = TclGetString(tmpPathPtr);
- Tcl_SetStringObj(pathPtr, path, tmpPathPtr->length);
+ path = TclGetStringFromObj(tmpPathPtr, &len);
+ Tcl_SetStringObj(pathPtr, path, len);
Tcl_DecrRefCount(tmpPathPtr);
} else {
/*
@@ -2842,8 +2893,8 @@ TclWinVolumeRelativeNormalize(
* also on drive C.
*/
- const char *drive = TclGetString(useThisCwd);
- size_t cwdLen = useThisCwd->length;
+ int cwdLen;
+ const char *drive = TclGetStringFromObj(useThisCwd, &cwdLen);
char drive_cur = path[0];
if (drive_cur >= 'a') {
@@ -2919,7 +2970,7 @@ TclpNativeToNormalized(
int len;
char *copy, *p;
- Tcl_WinTCharToUtf((const TCHAR *) clientData, -1, &ds);
+ Tcl_WinTCharToUtf((const WCHAR *) clientData, -1, &ds);
copy = Tcl_DStringValue(&ds);
len = Tcl_DStringLength(&ds);
@@ -2978,7 +3029,7 @@ TclNativeCreateNativeRep(
WCHAR *nativePathPtr = NULL;
const char *str;
Tcl_Obj *validPathPtr;
- size_t len;
+ int len;
WCHAR *wp;
if (TclFSCwdIsNative()) {
@@ -2992,7 +3043,11 @@ TclNativeCreateNativeRep(
if (validPathPtr == NULL) {
return NULL;
}
- /* refCount of validPathPtr was already incremented in Tcl_FSGetTranslatedPath */
+
+ /*
+ * refCount of validPathPtr was already incremented in
+ * Tcl_FSGetTranslatedPath
+ */
} else {
/*
* Make sure the normalized path is set.
@@ -3002,73 +3057,100 @@ TclNativeCreateNativeRep(
if (validPathPtr == NULL) {
return NULL;
}
- /* validPathPtr returned from Tcl_FSGetNormalizedPath is owned by Tcl, so incr refCount here */
+
+ /*
+ * validPathPtr returned from Tcl_FSGetNormalizedPath is owned by Tcl,
+ * so incr refCount here
+ */
+
Tcl_IncrRefCount(validPathPtr);
}
- str = Tcl_GetString(validPathPtr);
- len = validPathPtr->length;
+ str = Tcl_GetStringFromObj(validPathPtr, &len);
+
+ if (strlen(str) != (size_t) len) {
+ /*
+ * String contains NUL-bytes. This is invalid.
+ */
- if (strlen(str)!=(unsigned int)len) {
- /* String contains NUL-bytes. This is invalid. */
goto done;
}
- /* For a reserved device, strip a possible postfix ':' */
+
+ /*
+ * For a reserved device, strip a possible postfix ':'
+ */
+
len = WinIsReserved(str);
if (len == 0) {
- /* Let MultiByteToWideChar check for other invalid sequences, like
- * 0xC0 0x80 (== overlong NUL). See bug [3118489]: NUL in filenames */
+ /*
+ * Let MultiByteToWideChar check for other invalid sequences, like
+ * 0xC0 0x80 (== overlong NUL). See bug [3118489]: NUL in filenames
+ */
+
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, 0, 0);
if (len==0) {
goto done;
}
}
- /* Overallocate 6 chars, making some room for extended paths */
- wp = nativePathPtr = ckalloc( (len+6) * sizeof(WCHAR) );
+
+ /*
+ * Overallocate 6 chars, making some room for extended paths
+ */
+
+ wp = nativePathPtr = ckalloc((len + 6) * sizeof(WCHAR));
if (nativePathPtr==0) {
goto done;
}
- MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nativePathPtr, len+1);
+ MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str, -1, nativePathPtr,
+ len + 1);
+
/*
- ** If path starts with "//?/" or "\\?\" (extended path), translate
- ** any slashes to backslashes but leave the '?' intact
- */
- if ((str[0]=='\\' || str[0]=='/') && (str[1]=='\\' || str[1]=='/')
- && str[2]=='?' && (str[3]=='\\' || str[3]=='/')) {
+ * If path starts with "//?/" or "\\?\" (extended path), translate any
+ * slashes to backslashes but leave the '?' intact
+ */
+
+ if ((str[0] == '\\' || str[0] == '/') && (str[1] == '\\' || str[1] == '/')
+ && str[2] == '?' && (str[3] == '\\' || str[3] == '/')) {
wp[0] = wp[1] = wp[3] = '\\';
str += 4;
wp += 4;
}
+
/*
- ** If there is no "\\?\" prefix but there is a drive or UNC
- ** path prefix and the path is larger than MAX_PATH chars,
- ** no Win32 API function can handle that unless it is
- ** prefixed with the extended path prefix. See:
- ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
- **/
- if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z'))
- && str[1]==':') {
- if (wp==nativePathPtr && len>MAX_PATH && (str[2]=='\\' || str[2]=='/')) {
- memmove(wp+4, wp, len*sizeof(WCHAR));
- memcpy(wp, L"\\\\?\\", 4*sizeof(WCHAR));
+ * If there is no "\\?\" prefix but there is a drive or UNC path prefix
+ * and the path is larger than MAX_PATH chars, no Win32 API function can
+ * handle that unless it is prefixed with the extended path prefix. See:
+ * <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath>
+ */
+
+ if (((str[0] >= 'A' && str[0] <= 'Z') || (str[0] >= 'a' && str[0] <= 'z'))
+ && str[1] == ':') {
+ if (wp == nativePathPtr && len > MAX_PATH
+ && (str[2] == '\\' || str[2] == '/')) {
+ memmove(wp + 4, wp, len * sizeof(WCHAR));
+ memcpy(wp, L"\\\\?\\", 4 * sizeof(WCHAR));
wp += 4;
}
+
/*
- ** If (remainder of) path starts with "<drive>:",
- ** leave the ':' intact.
+ * If (remainder of) path starts with "<drive>:", leave the ':'
+ * intact.
*/
+
wp += 2;
- } else if (wp==nativePathPtr && len>MAX_PATH
- && (str[0]=='\\' || str[0]=='/')
- && (str[1]=='\\' || str[1]=='/') && str[2]!='?') {
- memmove(wp+6, wp, len*sizeof(WCHAR));
- memcpy(wp, L"\\\\?\\UNC", 7*sizeof(WCHAR));
+ } else if (wp == nativePathPtr && len > MAX_PATH
+ && (str[0] == '\\' || str[0] == '/')
+ && (str[1] == '\\' || str[1] == '/') && str[2] != '?') {
+ memmove(wp + 6, wp, len * sizeof(WCHAR));
+ memcpy(wp, L"\\\\?\\UNC", 7 * sizeof(WCHAR));
wp += 7;
}
+
/*
- ** In the remainder of the path, translate invalid characters to
- ** characters in the Unicode private use area.
- */
+ * In the remainder of the path, translate invalid characters to
+ * characters in the Unicode private use area.
+ */
+
while (*wp != '\0') {
if ((*wp < ' ') || wcschr(L"\"*:<>?|", *wp)) {
*wp |= 0xF000;
@@ -3079,7 +3161,6 @@ TclNativeCreateNativeRep(
}
done:
-
TclDecrRefCount(validPathPtr);
return nativePathPtr;
}
@@ -3112,7 +3193,7 @@ TclNativeDupInternalRep(
return NULL;
}
- len = sizeof(TCHAR) * (_tcslen((const TCHAR *) clientData) + 1);
+ len = sizeof(WCHAR) * (wcslen((const WCHAR *) clientData) + 1);
copy = ckalloc(len);
memcpy(copy, clientData, len);
@@ -3143,7 +3224,7 @@ TclpUtime(
{
int res = 0;
HANDLE fileHandle;
- const TCHAR *native;
+ const WCHAR *native;
DWORD attr = 0;
DWORD flags = FILE_ATTRIBUTE_NORMAL;
FILETIME lastAccessTime, lastModTime;
@@ -3194,7 +3275,7 @@ int
TclWinFileOwned(
Tcl_Obj *pathPtr) /* File whose ownership is to be checked */
{
- const TCHAR *native;
+ const WCHAR *native;
PSID ownerSid = NULL;
PSECURITY_DESCRIPTOR secd = NULL;
HANDLE token;
@@ -3205,21 +3286,28 @@ TclWinFileOwned(
native = Tcl_FSGetNativePath(pathPtr);
if (GetNamedSecurityInfo((LPTSTR) native, SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION, &ownerSid,
- NULL, NULL, NULL, &secd) != ERROR_SUCCESS) {
- /* Either not a file, or we do not have access to it in which
- case we are in all likelihood not the owner */
+ OWNER_SECURITY_INFORMATION, &ownerSid, NULL, NULL, NULL,
+ &secd) != ERROR_SUCCESS) {
+ /*
+ * Either not a file, or we do not have access to it in which case we
+ * are in all likelihood not the owner.
+ */
+
return 0;
}
/*
- * Getting the current process SID is a multi-step process.
- * We make the assumption that if a call fails, this process is
- * so underprivileged it could not possibly own anything. Normally
- * a process can *always* look up its own token.
+ * Getting the current process SID is a multi-step process. We make the
+ * assumption that if a call fails, this process is so underprivileged it
+ * could not possibly own anything. Normally a process can *always* look
+ * up its own token.
*/
+
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) {
- /* Find out how big the buffer needs to be */
+ /*
+ * Find out how big the buffer needs to be.
+ */
+
bufsz = 0;
GetTokenInformation(token, TokenUser, NULL, 0, &bufsz);
if (bufsz) {
@@ -3231,15 +3319,20 @@ TclWinFileOwned(
CloseHandle(token);
}
- /* Free allocations and be done */
- if (secd)
+ /*
+ * Free allocations and be done.
+ */
+
+ if (secd) {
LocalFree(secd); /* Also frees ownerSid */
- if (buf)
+ }
+ if (buf) {
ckfree(buf);
+ }
return (owned != 0); /* Convert non-0 to 1 */
}
-
+
/*
* Local Variables:
* mode: c