tclwinfile.c

来自「tcl是工具命令语言」· C语言 代码 · 共 2,275 行 · 第 1/5 页

C
2,275
字号
	    }        } else {	    /* We do have '/..' */	    len -= 3;	    remove++;        }    }    if (len < 4) {	if (len == 0) {	    /* 	     * Not sure if this is possible, but we pass it on	     * anyway 	     */	} else if (len == 1 && (name[0] == '/' || name[0] == '\\')) {	    /* Path is pointing to the root volume */	    return 1;	} else if ((name[1] == ':') 		   && (len == 2 || (name[2] == '/' || name[2] == '\\'))) {	    /* Path is of the form 'x:' or 'x:/' or 'x:\' */	    return 1;	}    }    return 0;}/* *---------------------------------------------------------------------- *  * NativeMatchType -- *  * This function needs a special case for a path which is a root * volume, because for NTFS root volumes, the getFileAttributesProc * returns a 'hidden' attribute when it should not. *  * We only ever make one call to a 'get attributes' routine here, * so that this function is as fast as possible.  Unfortunately, * it still means we have to make the call for every single file * we return from 'glob', which is not ideal. *  * Results: *  0 = file doesn't match *  1 = file matches *  *---------------------------------------------------------------------- */static int NativeMatchType(    int isDrive,              /* Is this a drive */    DWORD attr,               /* We already know the attributes                                * for the file */    CONST TCHAR* nativeName,  /* Native path to check */    Tcl_GlobTypeData *types)  /* Type description to match against */{    /*     * 'attr' represents the attributes of the file, but we only     * want to retrieve this info if it is absolutely necessary     * because it is an expensive call.  Unfortunately, to deal     * with hidden files properly, we must always retrieve it.     */    if (types == NULL) {	/* If invisible, don't return the file */	if (attr & FILE_ATTRIBUTE_HIDDEN && !isDrive) {	    return 0;	}    } else {	if (attr & FILE_ATTRIBUTE_HIDDEN && !isDrive) {	    /* If invisible */	    if ((types->perm == 0) || 		    !(types->perm & TCL_GLOB_PERM_HIDDEN)) {		return 0;	    }	} else {	    /* Visible */	    if (types->perm & TCL_GLOB_PERM_HIDDEN) {		return 0;	    }	}		if (types->perm != 0) {	    if (		((types->perm & TCL_GLOB_PERM_RONLY) &&			!(attr & FILE_ATTRIBUTE_READONLY)) ||		((types->perm & TCL_GLOB_PERM_R) &&			(0 /* File exists => R_OK on Windows */)) ||		((types->perm & TCL_GLOB_PERM_W) &&			(attr & FILE_ATTRIBUTE_READONLY)) ||		((types->perm & TCL_GLOB_PERM_X) &&			(!(attr & FILE_ATTRIBUTE_DIRECTORY)			 && !NativeIsExec(nativeName)))		) {		return 0;	    }	}	if ((types->type & TCL_GLOB_TYPE_DIR) 	    && (attr & FILE_ATTRIBUTE_DIRECTORY)) {	    /* Quicker test for directory, which is a common case */	    return 1;	} else if (types->type != 0) {	    unsigned short st_mode;	    int isExec = NativeIsExec(nativeName);	    	    st_mode = NativeStatMode(attr, 0, isExec);	    /*	     * In order bcdpfls as in 'find -t'	     */	    if (		((types->type & TCL_GLOB_TYPE_BLOCK) &&			S_ISBLK(st_mode)) ||		((types->type & TCL_GLOB_TYPE_CHAR) &&			S_ISCHR(st_mode)) ||		((types->type & TCL_GLOB_TYPE_DIR) &&			S_ISDIR(st_mode)) ||		((types->type & TCL_GLOB_TYPE_PIPE) &&			S_ISFIFO(st_mode)) ||		((types->type & TCL_GLOB_TYPE_FILE) &&			S_ISREG(st_mode))#ifdef S_ISSOCK		|| ((types->type & TCL_GLOB_TYPE_SOCK) &&			S_ISSOCK(st_mode))#endif		) {		/* Do nothing -- this file is ok */	    } else {#ifdef S_ISLNK		if (types->type & TCL_GLOB_TYPE_LINK) {		    st_mode = NativeStatMode(attr, 1, isExec);		    if (S_ISLNK(st_mode)) {			return 1;		    }		}#endif		return 0;	    }	}		    }     return 1;}/* *---------------------------------------------------------------------- * * TclpGetUserHome -- * *	This function takes the passed in user name and finds the *	corresponding home directory specified in the password file. * * Results: *	The result is a pointer to a string specifying the user's home *	directory, or NULL if the user's home directory could not be *	determined.  Storage for the result string is allocated in *	bufferPtr; the caller must call Tcl_DStringFree() when the result *	is no longer needed. * * Side effects: *	None. * *---------------------------------------------------------------------- */char *TclpGetUserHome(name, bufferPtr)    CONST char *name;		/* User name for desired home directory. */    Tcl_DString *bufferPtr;	/* Uninitialized or free DString filled				 * with name of user's home directory. */{    char *result;    HINSTANCE netapiInst;    result = NULL;    Tcl_DStringInit(bufferPtr);    netapiInst = LoadLibraryA("netapi32.dll");    if (netapiInst != NULL) {	NETAPIBUFFERFREEPROC *netApiBufferFreeProc;	NETGETDCNAMEPROC *netGetDCNameProc;	NETUSERGETINFOPROC *netUserGetInfoProc;	netApiBufferFreeProc = (NETAPIBUFFERFREEPROC *)		GetProcAddress(netapiInst, "NetApiBufferFree");	netGetDCNameProc = (NETGETDCNAMEPROC *) 		GetProcAddress(netapiInst, "NetGetDCName");	netUserGetInfoProc = (NETUSERGETINFOPROC *) 		GetProcAddress(netapiInst, "NetUserGetInfo");	if ((netUserGetInfoProc != NULL) && (netGetDCNameProc != NULL)		&& (netApiBufferFreeProc != NULL)) {	    USER_INFO_1 *uiPtr;	    Tcl_DString ds;	    int nameLen, badDomain;	    char *domain;	    WCHAR *wName, *wHomeDir, *wDomain;	    WCHAR buf[MAX_PATH];	    badDomain = 0;	    nameLen = -1;	    wDomain = NULL;	    domain = strchr(name, '@');	    if (domain != NULL) {		Tcl_DStringInit(&ds);		wName = Tcl_UtfToUniCharDString(domain + 1, -1, &ds);		badDomain = (*netGetDCNameProc)(NULL, wName,			(LPBYTE *) &wDomain);		Tcl_DStringFree(&ds);		nameLen = domain - name;	    }	    if (badDomain == 0) {		Tcl_DStringInit(&ds);		wName = Tcl_UtfToUniCharDString(name, nameLen, &ds);		if ((*netUserGetInfoProc)(wDomain, wName, 1,			(LPBYTE *) &uiPtr) == 0) {		    wHomeDir = uiPtr->usri1_home_dir;		    if ((wHomeDir != NULL) && (wHomeDir[0] != L'\0')) {			Tcl_UniCharToUtfDString(wHomeDir, lstrlenW(wHomeDir),				bufferPtr);		    } else {			/* 			 * User exists but has no home dir.  Return			 * "{Windows Drive}:/users/default".			 */			GetWindowsDirectoryW(buf, MAX_PATH);			Tcl_UniCharToUtfDString(buf, 2, bufferPtr);			Tcl_DStringAppend(bufferPtr, "/users/default", -1);		    }		    result = Tcl_DStringValue(bufferPtr);		    (*netApiBufferFreeProc)((void *) uiPtr);		}		Tcl_DStringFree(&ds);	    }	    if (wDomain != NULL) {		(*netApiBufferFreeProc)((void *) wDomain);	    }	}	FreeLibrary(netapiInst);    }    if (result == NULL) {	/*	 * Look in the "Password Lists" section of system.ini for the 	 * local user.  There are also entries in that section that begin 	 * with a "*" character that are used by Windows for other 	 * purposes; ignore user names beginning with a "*".	 */	char buf[MAX_PATH];	if (name[0] != '*') {	    if (GetPrivateProfileStringA("Password Lists", name, "", buf, 		    MAX_PATH, "system.ini") > 0) {		/* 		 * User exists, but there is no such thing as a home 		 * directory in system.ini.  Return "{Windows drive}:/".		 */		GetWindowsDirectoryA(buf, MAX_PATH);		Tcl_DStringAppend(bufferPtr, buf, 3);		result = Tcl_DStringValue(bufferPtr);	    }	}    }    return result;}/* *--------------------------------------------------------------------------- * * NativeAccess -- * *	This function replaces the library version of access(), fixing the *	following bugs: *  *	1. access() returns that all files have execute permission. * * Results: *	See access documentation. * * Side effects: *	See access documentation. * *--------------------------------------------------------------------------- */static intNativeAccess(    CONST TCHAR *nativePath,	/* Path of file to access (UTF-8). */    int mode)			/* Permission setting. */{    DWORD attr;    attr = (*tclWinProcs->getFileAttributesProc)(nativePath);    if (attr == 0xffffffff) {	/*	 * File doesn't exist. 	 */	TclWinConvertError(GetLastError());	return -1;    }    if ((mode & W_OK) && (attr & FILE_ATTRIBUTE_READONLY)) {	/*	 * File is not writable.	 */	Tcl_SetErrno(EACCES);	return -1;    }    if (mode & X_OK) {	if (attr & FILE_ATTRIBUTE_DIRECTORY) {	    /*	     * Directories are always executable. 	     */	    	    return 0;	}	if (NativeIsExec(nativePath)) {	    return 0;	}	Tcl_SetErrno(EACCES);	return -1;    }    return 0;}/* *---------------------------------------------------------------------- * * NativeIsExec -- * *	Determines if a path is executable.  On windows this is  *	simply defined by whether the path ends in any of ".exe", *	".com", or ".bat" * * Results: *	1 = executable, 0 = not. * *---------------------------------------------------------------------- */static intNativeIsExec(nativePath)    CONST TCHAR *nativePath;{    if (tclWinProcs->useWide) {	CONST WCHAR *path;	int len;		path = (CONST WCHAR*)nativePath;	len = wcslen(path);		if (len < 5) {	    return 0;	}		if (path[len-4] != L'.') {	    return 0;	}		if ((memcmp((char*)(path+len-3),L"exe",3*sizeof(WCHAR)) == 0)	    || (memcmp((char*)(path+len-3),L"com",3*sizeof(WCHAR)) == 0)	    || (memcmp((char*)(path+len-3),L"bat",3*sizeof(WCHAR)) == 0)) {	    return 1;	}    } else {	CONST char *p;		/* We are only looking for pure ascii */		p = strrchr((CONST char*)nativePath, '.');	if (p != NULL) {	    p++;	    /* 	     * Note: in the old code, stat considered '.pif' files as	     * executable, whereas access did not.	     */	    if ((stricmp(p, "exe") == 0)		    || (stricmp(p, "com") == 0)		    || (stricmp(p, "bat") == 0)) {		/*		 * File that ends with .exe, .com, or .bat is executable.		 */		return 1;	    }	}    }    return 0;}/* *---------------------------------------------------------------------- * * TclpObjChdir -- * *	This function replaces the library version of chdir(). * * Results: *	See chdir() documentation. * * Side effects: *	See chdir() documentation.   * *---------------------------------------------------------------------- */int TclpObjChdir(pathPtr)    Tcl_Obj *pathPtr; 	/* Path to new working directory. */{    int result;    CONST TCHAR *nativePath;    nativePath = (CONST TCHAR *) Tcl_FSGetNativePath(pathPtr);    result = (*tclWinProcs->setCurrentDirectoryProc)(nativePath);    if (result == 0) {	TclWinConvertError(GetLastError());	return -1;    }    return 0;}#ifdef __CYGWIN__/* *--------------------------------------------------------------------------- * * TclpReadlink -- * *     This function replaces the library version of readlink(). * * Results: *     The result is a pointer to a string specifying the contents *     of the symbolic link given by 'path', or NULL if the symbolic *     link could not be read.  Storage for the result string is *     allocated in bufferPtr; the caller must call Tcl_DStringFree() *     when the result is no longer needed. * * Side effects: *     See readlink() documentation. * *--------------------------------------------------------------------------- */char *TclpReadlink(path, linkPtr)    CONST char *path;          /* Path of file to readlink (UTF-8). */    Tcl_DString *linkPtr;      /* Uninitialized or free DString filled                                * with contents of link (UTF-8). */{    char link[MAXPATHLEN];    int length;

⌨️ 快捷键说明

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