⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclwinfile.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclWinFile.c -- * *      This file contains temporary wrappers around UNIX file handling *      functions. These wrappers map the UNIX functions to Win32 HANDLE-style *      files, which can be manipulated through the Win32 console redirection *      interfaces. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinFile.c,v 1.39 2002/07/20 01:01:41 vincentdarley Exp $ *///#define _WIN32_WINNT  0x0500#include "tclWinInt.h"#include <winioctl.h>#include <sys/stat.h>#include <shlobj.h>#include <lmaccess.h>		/* For TclpGetUserHome(). *//* * Declarations for 'link' related information.  This information * should come with VC++ 6.0, but is not in some older SDKs. * In any case it is not well documented. */#ifndef IO_REPARSE_TAG_RESERVED_ONE#  define IO_REPARSE_TAG_RESERVED_ONE 0x000000001#endif#ifndef IO_REPARSE_TAG_RESERVED_RANGE#  define IO_REPARSE_TAG_RESERVED_RANGE 0x000000001#endif#ifndef IO_REPARSE_TAG_VALID_VALUES#  define IO_REPARSE_TAG_VALID_VALUES 0x0E000FFFF#endif#ifndef IO_REPARSE_TAG_HSM#  define IO_REPARSE_TAG_HSM 0x0C0000004#endif#ifndef IO_REPARSE_TAG_NSS#  define IO_REPARSE_TAG_NSS 0x080000005#endif#ifndef IO_REPARSE_TAG_NSSRECOVER#  define IO_REPARSE_TAG_NSSRECOVER 0x080000006#endif#ifndef IO_REPARSE_TAG_SIS#  define IO_REPARSE_TAG_SIS 0x080000007#endif#ifndef IO_REPARSE_TAG_DFS#  define IO_REPARSE_TAG_DFS 0x080000008#endif#ifndef IO_REPARSE_TAG_RESERVED_ZERO#  define IO_REPARSE_TAG_RESERVED_ZERO 0x00000000#endif#ifndef FILE_FLAG_OPEN_REPARSE_POINT#  define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000#endif#ifndef IO_REPARSE_TAG_MOUNT_POINT#  define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003#endif#ifndef IsReparseTagValid#  define IsReparseTagValid(x) (!((x)&~IO_REPARSE_TAG_VALID_VALUES)&&((x)>IO_REPARSE_TAG_RESERVED_RANGE))#endif#ifndef IO_REPARSE_TAG_SYMBOLIC_LINK#  define IO_REPARSE_TAG_SYMBOLIC_LINK IO_REPARSE_TAG_RESERVED_ZERO#endif#ifndef FILE_SPECIAL_ACCESS#  define FILE_SPECIAL_ACCESS         (FILE_ANY_ACCESS)#endif#ifndef FSCTL_SET_REPARSE_POINT#  define FSCTL_SET_REPARSE_POINT    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)#  define FSCTL_GET_REPARSE_POINT    CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) #  define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS) #endif/*  * Maximum reparse buffer info size. The max user defined reparse * data is 16KB, plus there's a header. */#define MAX_REPARSE_SIZE	17000/* * Undocumented REPARSE_MOUNTPOINT_HEADER_SIZE structure definition. * This is found in winnt.h. *  * IMPORTANT: caution when using this structure, since the actual * structures used will want to store a full path in the 'PathBuffer' * field, but there isn't room (there's only a single WCHAR!).  Therefore * one must artificially create a larger space of memory and then cast it * to this type.  We use the 'DUMMY_REPARSE_BUFFER' struct just below to * deal with this problem. */#define REPARSE_MOUNTPOINT_HEADER_SIZE   8#ifndef REPARSE_DATA_BUFFER_HEADER_SIZEtypedef struct _REPARSE_DATA_BUFFER {    DWORD  ReparseTag;    WORD   ReparseDataLength;    WORD   Reserved;    union {        struct {            WORD   SubstituteNameOffset;            WORD   SubstituteNameLength;            WORD   PrintNameOffset;            WORD   PrintNameLength;            WCHAR PathBuffer[1];        } SymbolicLinkReparseBuffer;        struct {            WORD   SubstituteNameOffset;            WORD   SubstituteNameLength;            WORD   PrintNameOffset;            WORD   PrintNameLength;            WCHAR PathBuffer[1];        } MountPointReparseBuffer;        struct {            BYTE   DataBuffer[1];        } GenericReparseBuffer;    };} REPARSE_DATA_BUFFER;#endiftypedef struct {    REPARSE_DATA_BUFFER dummy;    WCHAR  dummyBuf[MAX_PATH*3];} DUMMY_REPARSE_BUFFER;/* Other typedefs required by this code */static time_t		ToCTime(FILETIME fileTime);typedef NET_API_STATUS NET_API_FUNCTION NETUSERGETINFOPROC	(LPWSTR servername, LPWSTR username, DWORD level, LPBYTE *bufptr);typedef NET_API_STATUS NET_API_FUNCTION NETAPIBUFFERFREEPROC	(LPVOID Buffer);typedef NET_API_STATUS NET_API_FUNCTION NETGETDCNAMEPROC	(LPWSTR servername, LPWSTR domainname, LPBYTE *bufptr);/* * Declarations for local procedures defined in this file: */static int NativeAccess(CONST TCHAR *path, int mode);static int NativeStat(CONST TCHAR *path, Tcl_StatBuf *statPtr, int checkLinks);static int NativeIsExec(CONST TCHAR *path);static int NativeReadReparse(CONST TCHAR* LinkDirectory, 			     REPARSE_DATA_BUFFER* buffer);static int NativeWriteReparse(CONST TCHAR* LinkDirectory, 			      REPARSE_DATA_BUFFER* buffer);static int NativeMatchType(CONST char *name, int nameLen, 			   CONST TCHAR* nativeName, Tcl_GlobTypeData *types);static int WinIsDrive(CONST char *name, int nameLen);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);/* *-------------------------------------------------------------------- * * WinLink * * Make a link from source to target.  *-------------------------------------------------------------------- */static int WinLink(LinkSource, LinkTarget, linkAction)    CONST TCHAR* LinkSource;    CONST TCHAR* LinkTarget;    int linkAction;{    WCHAR	tempFileName[MAX_PATH];    TCHAR*	tempFilePart;    int         attr;        /* Get the full path referenced by the target */    if (!(*tclWinProcs->getFullPathNameProc)(LinkTarget, 			  MAX_PATH, tempFileName, &tempFilePart)) {	/* Invalid file */	TclWinConvertError(GetLastError());	return -1;    }    /* Make sure source file doesn't exist */    attr = (*tclWinProcs->getFileAttributesProc)(LinkSource);    if (attr != 0xffffffff) {	Tcl_SetErrno(EEXIST);	return -1;    }    /* Get the full path referenced by the directory */    if (!(*tclWinProcs->getFullPathNameProc)(LinkSource, 			  MAX_PATH, tempFileName, &tempFilePart)) {	/* Invalid file */	TclWinConvertError(GetLastError());	return -1;    }    /* Check the target */    attr = (*tclWinProcs->getFileAttributesProc)(LinkTarget);    if (attr == 0xffffffff) {	/* The target doesn't exist */	TclWinConvertError(GetLastError());	return -1;    } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {	/* It is a file */	if (tclWinProcs->createHardLinkProc == NULL) {	    Tcl_SetErrno(ENOTDIR);	    return -1;	}	if (linkAction & TCL_CREATE_HARD_LINK) {	    if (!(*tclWinProcs->createHardLinkProc)(LinkSource, LinkTarget, NULL)) {		TclWinConvertError(GetLastError());		return -1;	    }	    return 0;	} else if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {	    /* Can't symlink files */	    Tcl_SetErrno(ENOTDIR);	    return -1;	} else {	    Tcl_SetErrno(ENODEV);	    return -1;	}    } else {	if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {	    return WinSymLinkDirectory(LinkSource, LinkTarget);	} else if (linkAction & TCL_CREATE_HARD_LINK) {	    /* Can't hard link directories */	    Tcl_SetErrno(EISDIR);	    return -1;	} else {	    Tcl_SetErrno(ENODEV);	    return -1;	}    }}/* *-------------------------------------------------------------------- * * WinReadLink * * What does 'LinkSource' point to?  We need the original 'pathPtr' * just so we can construct a path object in the correct filesystem. *-------------------------------------------------------------------- */static Tcl_Obj* WinReadLink(LinkSource)    CONST TCHAR* LinkSource;{    WCHAR	tempFileName[MAX_PATH];    TCHAR*	tempFilePart;    int         attr;        /* Get the full path referenced by the target */    if (!(*tclWinProcs->getFullPathNameProc)(LinkSource, 			  MAX_PATH, tempFileName, &tempFilePart)) {	/* Invalid file */	TclWinConvertError(GetLastError());	return NULL;    }    /* Make sure source file does exist */    attr = (*tclWinProcs->getFileAttributesProc)(LinkSource);    if (attr == 0xffffffff) {	/* The source doesn't exist */	TclWinConvertError(GetLastError());	return NULL;    } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {	/* It is a file - this is not yet supported */	Tcl_SetErrno(ENOTDIR);	return NULL;    } else {	return WinReadLinkDirectory(LinkSource);    }}/* *-------------------------------------------------------------------- * * WinSymLinkDirectory * * This routine creates a NTFS junction, using the undocumented * FSCTL_SET_REPARSE_POINT structure Win2K uses for mount points * and junctions. * * Assumption that LinkTarget is a valid, existing directory. *  * Returns zero on success. *-------------------------------------------------------------------- */static int WinSymLinkDirectory(LinkDirectory, LinkTarget)    CONST TCHAR* LinkDirectory;    CONST TCHAR* LinkTarget;{    DUMMY_REPARSE_BUFFER dummy;    REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER*)&dummy;    int         len;    WCHAR       nativeTarget[MAX_PATH];    WCHAR       *loop;        /* Make the native target name */    memcpy((VOID*)nativeTarget, (VOID*)L"\\??\\", 4*sizeof(WCHAR));    memcpy((VOID*)(nativeTarget + 4), (VOID*)LinkTarget, 	   sizeof(WCHAR)*(1+wcslen((WCHAR*)LinkTarget)));    len = wcslen(nativeTarget);    /*      * We must have backslashes only.  This is VERY IMPORTANT.     * If we have any forward slashes everything appears to work,     * but the resulting symlink is useless!     */    for (loop = nativeTarget; *loop != 0; loop++) {	if (*loop == L'/') *loop = L'\\';    }    if ((nativeTarget[len-1] == L'\\') && (nativeTarget[len-2] != L':')) {	nativeTarget[len-1] = 0;    }        /* Build the reparse info */    memset(reparseBuffer, 0, sizeof(DUMMY_REPARSE_BUFFER));    reparseBuffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;    reparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength =       wcslen(nativeTarget) * sizeof(WCHAR);    reparseBuffer->Reserved = 0;    reparseBuffer->SymbolicLinkReparseBuffer.PrintNameLength = 0;    reparseBuffer->SymbolicLinkReparseBuffer.PrintNameOffset =       reparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength       + sizeof(WCHAR);    memcpy(reparseBuffer->SymbolicLinkReparseBuffer.PathBuffer, nativeTarget,       sizeof(WCHAR)       + reparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength);    reparseBuffer->ReparseDataLength =       reparseBuffer->SymbolicLinkReparseBuffer.SubstituteNameLength + 12;	    return NativeWriteReparse(LinkDirectory, reparseBuffer);}/* *-------------------------------------------------------------------- * * TclWinSymLinkCopyDirectory * * Copy a Windows NTFS junction.  This function assumes that * LinkOriginal exists and is a valid junction point, and that * LinkCopy does not exist. *  * Returns zero on success. *-------------------------------------------------------------------- */int TclWinSymLinkCopyDirectory(LinkOriginal, LinkCopy)    CONST TCHAR* LinkOriginal;  /* Existing junction - reparse point */    CONST TCHAR* LinkCopy;      /* Will become a duplicate junction */{    DUMMY_REPARSE_BUFFER dummy;    REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER*)&dummy;        if (NativeReadReparse(LinkOriginal, reparseBuffer)) {	return -1;    }    return NativeWriteReparse(LinkCopy, reparseBuffer);}/* *-------------------------------------------------------------------- * * TclWinSymLinkDelete * * Delete a Windows NTFS junction.  Once the junction information * is deleted, the filesystem object becomes an ordinary directory. * Unless 'linkOnly' is given, that directory is also removed. *  * Assumption that LinkOriginal is a valid, existing junction. *  * Returns zero on success. *-------------------------------------------------------------------- */int TclWinSymLinkDelete(LinkOriginal, linkOnly)    CONST TCHAR* LinkOriginal;    int linkOnly;{    /* It is a symbolic link -- remove it */    DUMMY_REPARSE_BUFFER dummy;    REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER*)&dummy;    HANDLE hFile;    int returnedLength;    memset(reparseBuffer, 0, sizeof(DUMMY_REPARSE_BUFFER));    reparseBuffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;    hFile = (*tclWinProcs->createFileProc)(LinkOriginal, GENERIC_WRITE, 0,	NULL, OPEN_EXISTING, 	FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL);    if (hFile != INVALID_HANDLE_VALUE) {	if (!DeviceIoControl(hFile, FSCTL_DELETE_REPARSE_POINT, reparseBuffer, 			     REPARSE_MOUNTPOINT_HEADER_SIZE,			     NULL, 0, &returnedLength, NULL)) {		    /* Error setting junction */	    TclWinConvertError(GetLastError());	    CloseHandle(hFile);	} else {	    CloseHandle(hFile);	    if (!linkOnly) {	        (*tclWinProcs->removeDirectoryProc)(LinkOriginal);	    }	    return 0;	}    }    return -1;}/* *-------------------------------------------------------------------- * * WinReadLinkDirectory * * This routine reads a NTFS junction, using the undocumented * FSCTL_GET_REPARSE_POINT structure Win2K uses for mount points * and junctions. * * Assumption that LinkDirectory is a valid, existing directory. *  * Returns a Tcl_Obj with refCount of 1 (i.e. owned by the caller). *-------------------------------------------------------------------- */static Tcl_Obj* WinReadLinkDirectory(LinkDirectory)    CONST TCHAR* LinkDirectory;{    int attr;    DUMMY_REPARSE_BUFFER dummy;    REPARSE_DATA_BUFFER *reparseBuffer = (REPARSE_DATA_BUFFER*)&dummy;        attr = (*tclWinProcs->getFileAttributesProc)(LinkDirectory);    if (!(attr & FILE_ATTRIBUTE_REPARSE_POINT)) {	Tcl_SetErrno(EINVAL);	return NULL;    }    if (NativeReadReparse(LinkDirectory, reparseBuffer)) {        return NULL;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -