diff options
Diffstat (limited to 'unix/tclUnixFile.c')
-rw-r--r-- | unix/tclUnixFile.c | 994 |
1 files changed, 326 insertions, 668 deletions
diff --git a/unix/tclUnixFile.c b/unix/tclUnixFile.c index a4426b7..4ba2e47 100644 --- a/unix/tclUnixFile.c +++ b/unix/tclUnixFile.c @@ -1,8 +1,8 @@ /* * tclUnixFile.c -- * - * This file contains wrappers around UNIX file handling functions. - * These wrappers mask differences between Windows and UNIX. + * This file contains wrappers around UNIX file handling functions. + * These wrappers mask differences between Windows and UNIX. * * Copyright (c) 1995-1998 Sun Microsystems, Inc. * @@ -11,45 +11,62 @@ */ #include "tclInt.h" -#include "tclFileSystem.h" +#include "tclPort.h" + +static int NativeMatchType(CONST char* nativeName, Tcl_GlobTypeData *types); -static int NativeMatchType(Tcl_Interp *interp, const char* nativeEntry, - const char* nativeName, Tcl_GlobTypeData *types); /* *--------------------------------------------------------------------------- * * TclpFindExecutable -- * - * This function computes the absolute path name of the current + * This procedure computes the absolute path name of the current * application, given its argv[0] value. For Cygwin, argv[0] is * ignored and the path is determined the same as under win32. * * Results: - * None. + * A dirty UTF string that is the path to the executable. At this + * point we may not know the system encoding. Convert the native + * string value to UTF using the default encoding. The assumption + * is that we will still be able to parse the path given the path + * name contains ASCII string and '/' chars do not conflict with + * other UTF chars. * * Side effects: - * The computed path name is stored as a ProcessGlobalValue. + * The variable tclNativeExecutableName gets filled in with the file + * name for the application, if we figured it out. If we couldn't + * figure it out, tclNativeExecutableName is set to NULL. * *--------------------------------------------------------------------------- */ -void -TclpFindExecutable( - const char *argv0) /* The value of the application's argv[0] +char * +TclpFindExecutable(argv0) + CONST char *argv0; /* The value of the application's argv[0] * (native). */ { - Tcl_Encoding encoding; -#ifdef __CYGWIN__ int length; +#ifdef __CYGWIN__ char buf[PATH_MAX * TCL_UTF_MAX + 1]; char name[PATH_MAX * TCL_UTF_MAX + 1]; +#else + CONST char *name, *p; + Tcl_StatBuf statBuf; + Tcl_DString buffer, nameString; +#endif + + if (tclNativeExecutableName != NULL) { + return tclNativeExecutableName; + } + +#ifdef __CYGWIN__ /* Make some symbols available without including <windows.h> */ # define CP_UTF8 65001 - DLLIMPORT extern int cygwin_conv_to_full_posix_path(const char *, char *); - DLLIMPORT extern __stdcall int GetModuleFileNameW(void *, const char *, int); - DLLIMPORT extern __stdcall int WideCharToMultiByte(int, int, const char *, int, + extern int cygwin_conv_to_full_posix_path(const char *, char *); + extern __stdcall int GetModuleFileNameW(void *, const char *, int); + extern __stdcall int WideCharToMultiByte(int, int, const char *, int, const char *, int, const char *, const char *); GetModuleFileNameW(NULL, name, PATH_MAX); @@ -60,16 +77,12 @@ TclpFindExecutable( /* Strip '.exe' part. */ length -= 4; } - encoding = Tcl_GetEncoding(NULL, NULL); - TclSetObjNameOfExecutable( - Tcl_NewStringObj(name, length), encoding); + tclNativeExecutableName = (char *) ckalloc(length + 1); + memcpy(tclNativeExecutableName, name, length); + buf[length] = '\0'; #else - const char *name, *p; - Tcl_StatBuf statBuf; - Tcl_DString buffer, nameString, cwd, utfName; - if (argv0 == NULL) { - return; + return NULL; } Tcl_DStringInit(&buffer); @@ -77,8 +90,8 @@ TclpFindExecutable( for (p = name; *p != '\0'; p++) { if (*p == '/') { /* - * The name contains a slash, so use the name directly without - * doing a path search. + * The name contains a slash, so use the name directly + * without doing a path search. */ goto gotName; @@ -88,8 +101,8 @@ TclpFindExecutable( p = getenv("PATH"); /* INTL: Native. */ if (p == NULL) { /* - * There's no PATH environment variable; use the default that is used - * by sh. + * There's no PATH environment variable; use the default that + * is used by sh. */ p = ":/bin:/usr/bin"; @@ -102,12 +115,13 @@ TclpFindExecutable( } /* - * Search through all the directories named in the PATH variable to see if - * argv[0] is in one of them. If so, use that file name. + * Search through all the directories named in the PATH variable + * to see if argv[0] is in one of them. If so, use that file + * name. */ while (1) { - while (TclIsSpaceProc(*p)) { + while (isspace(UCHAR(*p))) { /* INTL: BUG */ p++; } name = p; @@ -142,64 +156,53 @@ TclpFindExecutable( p++; } } - TclSetObjNameOfExecutable(Tcl_NewObj(), NULL); goto done; /* - * If the name starts with "/" then just store it + * If the name starts with "/" then just copy it to tclExecutableName. */ - gotName: +gotName: #ifdef DJGPP - if (name[1] == ':') + if (name[1] == ':') { #else - if (name[0] == '/') + if (name[0] == '/') { #endif - { - encoding = Tcl_GetEncoding(NULL, NULL); - Tcl_ExternalToUtfDString(encoding, name, -1, &utfName); - TclSetObjNameOfExecutable( - Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding); - Tcl_DStringFree(&utfName); + Tcl_ExternalToUtfDString(NULL, name, -1, &nameString); + tclNativeExecutableName = (char *) + ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1)); + strcpy(tclNativeExecutableName, Tcl_DStringValue(&nameString)); + Tcl_DStringFree(&nameString); goto done; } /* - * The name is relative to the current working directory. First strip off - * a leading "./", if any, then add the full path name of the current - * working directory. + * The name is relative to the current working directory. First + * strip off a leading "./", if any, then add the full path name of + * the current working directory. */ if ((name[0] == '.') && (name[1] == '/')) { name += 2; } - Tcl_DStringInit(&nameString); - Tcl_DStringAppend(&nameString, name, -1); - - TclpGetCwd(NULL, &cwd); + Tcl_ExternalToUtfDString(NULL, name, -1, &nameString); Tcl_DStringFree(&buffer); - Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd), - Tcl_DStringLength(&cwd), &buffer); - if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') { - Tcl_DStringAppend(&buffer, "/", 1); - } - Tcl_DStringFree(&cwd); - Tcl_DStringAppend(&buffer, Tcl_DStringValue(&nameString), - Tcl_DStringLength(&nameString)); + TclpGetCwd(NULL, &buffer); + + length = Tcl_DStringLength(&buffer) + Tcl_DStringLength(&nameString) + 2; + tclNativeExecutableName = (char *) ckalloc((unsigned) length); + strcpy(tclNativeExecutableName, Tcl_DStringValue(&buffer)); + tclNativeExecutableName[Tcl_DStringLength(&buffer)] = '/'; + strcpy(tclNativeExecutableName + Tcl_DStringLength(&buffer) + 1, + Tcl_DStringValue(&nameString)); Tcl_DStringFree(&nameString); - - encoding = Tcl_GetEncoding(NULL, NULL); - Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&buffer), -1, - &utfName); - TclSetObjNameOfExecutable( - Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding); - Tcl_DStringFree(&utfName); - - done: + +done: Tcl_DStringFree(&buffer); #endif + return tclNativeExecutableName; } /* @@ -207,101 +210,80 @@ TclpFindExecutable( * * TclpMatchInDirectory -- * - * This routine is used by the globbing code to search a directory for - * all files which match a given pattern. + * This routine is used by the globbing code to search a + * directory for all files which match a given pattern. * - * Results: - * The return value is a standard Tcl result indicating whether an error - * occurred in globbing. Errors are left in interp, good results are - * [lappend]ed to resultPtr (which must be a valid object). + * Results: + * The return value is a standard Tcl result indicating whether an + * error occurred in globbing. Errors are left in interp, good + * results are lappended to resultPtr (which must be a valid object) * * Side effects: * None. * - *---------------------------------------------------------------------- - */ + *---------------------------------------------------------------------- */ int -TclpMatchInDirectory( - Tcl_Interp *interp, /* Interpreter to receive errors. */ - Tcl_Obj *resultPtr, /* List object to lappend results. */ - Tcl_Obj *pathPtr, /* Contains path to directory to search. */ - const char *pattern, /* Pattern to match against. */ - Tcl_GlobTypeData *types) /* Object containing list of acceptable types. +TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types) + Tcl_Interp *interp; /* Interpreter to receive errors. */ + Tcl_Obj *resultPtr; /* List object to lappend results. */ + Tcl_Obj *pathPtr; /* Contains path to directory to search. */ + CONST char *pattern; /* Pattern to match against. */ + Tcl_GlobTypeData *types; /* Object containing list of acceptable types. * May be NULL. In particular the directory * flag is very important. */ { - const char *native; + CONST char *native; Tcl_Obj *fileNamePtr; - int matchResult = 0; - - if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) { - /* - * The native filesystem never adds mounts. - */ - - return TCL_OK; - } fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr); if (fileNamePtr == NULL) { return TCL_ERROR; } - + if (pattern == NULL || (*pattern == '\0')) { - /* - * Match a file directly. - */ - - Tcl_Obj *tailPtr; - const char *nativeTail; - - native = Tcl_FSGetNativePath(pathPtr); - tailPtr = TclPathPart(interp, pathPtr, TCL_PATH_TAIL); - nativeTail = Tcl_FSGetNativePath(tailPtr); - matchResult = NativeMatchType(interp, native, nativeTail, types); - if (matchResult == 1) { + /* Match a file directly */ + native = (CONST char*) Tcl_FSGetNativePath(pathPtr); + if (NativeMatchType(native, types)) { Tcl_ListObjAppendElement(interp, resultPtr, pathPtr); } - Tcl_DecrRefCount(tailPtr); Tcl_DecrRefCount(fileNamePtr); + return TCL_OK; } else { DIR *d; Tcl_DirEntry *entryPtr; - const char *dirName; - int dirLength, nativeDirLen; - int matchHidden, matchHiddenPat; + CONST char *dirName; + int dirLength; + int matchHidden; + int nativeDirLen; Tcl_StatBuf statBuf; - Tcl_DString ds; /* native encoding of dir */ - Tcl_DString dsOrig; /* utf-8 encoding of dir */ + Tcl_DString ds; /* native encoding of dir */ + Tcl_DString dsOrig; /* utf-8 encoding of dir */ Tcl_DStringInit(&dsOrig); dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength); Tcl_DStringAppend(&dsOrig, dirName, dirLength); - + /* * Make sure that the directory part of the name really is a - * directory. If the directory name is "", use the name "." instead, - * because some UNIX systems don't treat "" like "." automatically. - * Keep the "" for use in generating file names, otherwise "glob - * foo.c" would return "./foo.c". + * directory. If the directory name is "", use the name "." + * instead, because some UNIX systems don't treat "" like "." + * automatically. Keep the "" for use in generating file names, + * otherwise "glob foo.c" would return "./foo.c". */ if (dirLength == 0) { dirName = "."; } else { dirName = Tcl_DStringValue(&dsOrig); - - /* - * Make sure we have a trailing directory delimiter. - */ - + /* Make sure we have a trailing directory delimiter */ if (dirName[dirLength-1] != '/') { dirName = Tcl_DStringAppend(&dsOrig, "/", 1); dirLength++; } } - + Tcl_DecrRefCount(fileNamePtr); + /* * Now open the directory for reading and iterate over the contents. */ @@ -312,21 +294,17 @@ TclpMatchInDirectory( || !S_ISDIR(statBuf.st_mode)) { Tcl_DStringFree(&dsOrig); Tcl_DStringFree(&ds); - Tcl_DecrRefCount(fileNamePtr); return TCL_OK; } d = opendir(native); /* INTL: Native. */ if (d == NULL) { Tcl_DStringFree(&ds); - if (interp != NULL) { - Tcl_ResetResult(interp); - Tcl_AppendResult(interp, "couldn't read directory \"", - Tcl_DStringValue(&dsOrig), "\": ", - Tcl_PosixError(interp), NULL); - } + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "couldn't read directory \"", + Tcl_DStringValue(&dsOrig), "\": ", + Tcl_PosixError(interp), (char *) NULL); Tcl_DStringFree(&dsOrig); - Tcl_DecrRefCount(fileNamePtr); return TCL_ERROR; } @@ -335,239 +313,157 @@ TclpMatchInDirectory( /* * Check to see if -type or the pattern requests hidden files. */ + matchHidden = ((types && (types->perm & TCL_GLOB_PERM_HIDDEN)) || + ((pattern[0] == '.') + || ((pattern[0] == '\\') && (pattern[1] == '.')))); - matchHiddenPat = (pattern[0] == '.') - || ((pattern[0] == '\\') && (pattern[1] == '.')); - matchHidden = matchHiddenPat - || (types && (types->perm & TCL_GLOB_PERM_HIDDEN)); - while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */ + while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */ Tcl_DString utfDs; - const char *utfname; + CONST char *utfname; - /* - * Skip this file if it doesn't agree with the hidden parameters - * requested by the user (via -type or pattern). + /* + * Skip this file if it doesn't agree with the hidden + * parameters requested by the user (via -type or pattern). */ - if (*entryPtr->d_name == '.') { - if (!matchHidden) { - continue; - } + if (!matchHidden) continue; } else { -#ifdef MAC_OSX_TCL - if (matchHiddenPat) { - continue; - } - /* Also need to check HFS hidden flag in TclMacOSXMatchType. */ -#else - if (matchHidden) { - continue; - } -#endif + if (matchHidden) continue; } /* * Now check to see if the file matches, according to both type - * and pattern. If so, add the file to the result. + * and pattern. If so, add the file to the result. */ - utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1, - &utfDs); + utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, + -1, &utfDs); if (Tcl_StringCaseMatch(utfname, pattern, 0)) { int typeOk = 1; if (types != NULL) { Tcl_DStringSetLength(&ds, nativeDirLen); native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1); - matchResult = NativeMatchType(interp, native, - entryPtr->d_name, types); - typeOk = (matchResult == 1); + typeOk = NativeMatchType(native, types); } if (typeOk) { - Tcl_ListObjAppendElement(interp, resultPtr, + Tcl_ListObjAppendElement(interp, resultPtr, TclNewFSPathObj(pathPtr, utfname, - Tcl_DStringLength(&utfDs))); + Tcl_DStringLength(&utfDs))); } } Tcl_DStringFree(&utfDs); - if (matchResult < 0) { - break; - } } closedir(d); Tcl_DStringFree(&ds); Tcl_DStringFree(&dsOrig); - Tcl_DecrRefCount(fileNamePtr); - } - if (matchResult < 0) { - return TCL_ERROR; + return TCL_OK; } - return TCL_OK; } - -/* - *---------------------------------------------------------------------- - * - * NativeMatchType -- - * - * This routine is used by the globbing code to check if a file matches a - * given type description. - * - * Results: - * The return value is 1, 0 or -1 indicating whether the file matches the - * given criteria, does not match them, or an error occurred (in which - * case an error is left in interp). - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int +static int NativeMatchType( - Tcl_Interp *interp, /* Interpreter to receive errors. */ - const char *nativeEntry, /* Native path to check. */ - const char *nativeName, /* Native filename to check. */ - Tcl_GlobTypeData *types) /* Type description to match against. */ + CONST char* nativeEntry, /* Native path to check */ + Tcl_GlobTypeData *types) /* Type description to match against */ { Tcl_StatBuf buf; - if (types == NULL) { - /* - * Simply check for the file's existence, but do it with lstat, in - * case it is a link to a file which doesn't exist (since that case - * would not show up if we used 'access' or 'stat') + /* + * Simply check for the file's existence, but do it + * with lstat, in case it is a link to a file which + * doesn't exist (since that case would not show up + * if we used 'access' or 'stat') */ - if (TclOSlstat(nativeEntry, &buf) != 0) { return 0; } - return 1; - } - - if (types->perm != 0) { - if (TclOSstat(nativeEntry, &buf) != 0) { - /* - * Either the file has disappeared between the 'readdir' call and - * the 'stat' call, or the file is a link to a file which doesn't - * exist (which we could ascertain with lstat), or there is some - * other strange problem. In all these cases, we define this to - * mean the file does not match any defined permission, and - * therefore it is not added to the list of files to return. + } else { + if (types->perm != 0) { + if (TclOSstat(nativeEntry, &buf) != 0) { + /* + * Either the file has disappeared between the + * 'readdir' call and the 'stat' call, or + * the file is a link to a file which doesn't + * exist (which we could ascertain with + * lstat), or there is some other strange + * problem. In all these cases, we define this + * to mean the file does not match any defined + * permission, and therefore it is not + * added to the list of files to return. + */ + return 0; + } + + /* + * readonly means that there are NO write permissions + * (even for user), but execute is OK for anybody */ - - return 0; - } - - /* - * readonly means that there are NO write permissions (even for user), - * but execute is OK for anybody OR that the user immutable flag is - * set (where supported). - */ - - if (((types->perm & TCL_GLOB_PERM_RONLY) && -#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) - !(buf.st_flags & UF_IMMUTABLE) && -#endif - (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) || - ((types->perm & TCL_GLOB_PERM_R) && - (access(nativeEntry, R_OK) != 0)) || - ((types->perm & TCL_GLOB_PERM_W) && - (access(nativeEntry, W_OK) != 0)) || - ((types->perm & TCL_GLOB_PERM_X) && - (access(nativeEntry, X_OK) != 0)) -#ifndef MAC_OSX_TCL - || ((types->perm & TCL_GLOB_PERM_HIDDEN) && - (*nativeName != '.')) -#endif + if (((types->perm & TCL_GLOB_PERM_RONLY) && + (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) || + ((types->perm & TCL_GLOB_PERM_R) && + (access(nativeEntry, R_OK) != 0)) || + ((types->perm & TCL_GLOB_PERM_W) && + (access(nativeEntry, W_OK) != 0)) || + ((types->perm & TCL_GLOB_PERM_X) && + (access(nativeEntry, X_OK) != 0)) ) { - return 0; + return 0; + } } - } - if (types->type != 0) { - if (types->perm == 0) { - /* - * We haven't yet done a stat on the file. - */ - - if (TclOSstat(nativeEntry, &buf) != 0) { - /* - * Posix error occurred. The only ok case is if this is a link - * to a nonexistent file, and the user did 'glob -l'. So we - * check that here: - */ - - if (types->type & TCL_GLOB_TYPE_LINK) { - if (TclOSlstat(nativeEntry, &buf) == 0) { - if (S_ISLNK(buf.st_mode)) { - return 1; + if (types->type != 0) { + if (types->perm == 0) { + /* We haven't yet done a stat on the file */ + if (TclOSstat(nativeEntry, &buf) != 0) { + /* + * Posix error occurred. The only ok + * case is if this is a link to a nonexistent + * file, and the user did 'glob -l'. So + * we check that here: + */ + if (types->type & TCL_GLOB_TYPE_LINK) { + if (TclOSlstat(nativeEntry, &buf) == 0) { + if (S_ISLNK(buf.st_mode)) { + return 1; + } } } + return 0; } - return 0; } - } - - /* - * In order bcdpsfl as in 'find -t' - */ - - if ( ((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_DIR) && S_ISDIR(buf.st_mode)) || - ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))|| -#ifdef S_ISSOCK - ((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))|| -#endif /* S_ISSOCK */ - ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))) { /* - * Do nothing - this file is ok. + * In order bcdpfls as in 'find -t' */ - } else { + if ( + ((types->type & TCL_GLOB_TYPE_BLOCK) && + S_ISBLK(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_CHAR) && + S_ISCHR(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_DIR) && + S_ISDIR(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_PIPE) && + S_ISFIFO(buf.st_mode)) || + ((types->type & TCL_GLOB_TYPE_FILE) && + S_ISREG(buf.st_mode)) +#ifdef S_ISSOCK + || ((types->type & TCL_GLOB_TYPE_SOCK) && + S_ISSOCK(buf.st_mode)) +#endif /* S_ISSOCK */ + ) { + /* Do nothing -- this file is ok */ + } else { #ifdef S_ISLNK - if (types->type & TCL_GLOB_TYPE_LINK) { - if (TclOSlstat(nativeEntry, &buf) == 0) { - if (S_ISLNK(buf.st_mode)) { - goto filetypeOK; + if (types->type & TCL_GLOB_TYPE_LINK) { + if (TclOSlstat(nativeEntry, &buf) == 0) { + if (S_ISLNK(buf.st_mode)) { + return 1; + } } } - } #endif /* S_ISLNK */ - return 0; - } - } - filetypeOK: - - /* - * If we're on OSX, we also have to worry about matching the file creator - * code (if specified). Do that now. - */ - -#ifdef MAC_OSX_TCL - if (types->macType != NULL || types->macCreator != NULL || - (types->perm & TCL_GLOB_PERM_HIDDEN)) { - int matchResult; - - if (types->perm == 0 && types->type == 0) { - /* - * We haven't yet done a stat on the file. - */ - - if (TclOSstat(nativeEntry, &buf) != 0) { return 0; } } - - matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName, - &buf, types); - if (matchResult != 1) { - return matchResult; - } } -#endif /* MAC_OSX_TCL */ - return 1; } @@ -576,15 +472,15 @@ NativeMatchType( * * TclpGetUserHome -- * - * This function takes the specified user name and finds their home - * directory. + * This function takes the specified user name and finds their + * home directory. * * 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. + * 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. @@ -592,23 +488,26 @@ NativeMatchType( *---------------------------------------------------------------------- */ -const char * -TclpGetUserHome( - 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 * +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. */ { struct passwd *pwPtr; Tcl_DString ds; - const char *native = Tcl_UtfToExternalDString(NULL, name, -1, &ds); + CONST char *native; - pwPtr = TclpGetPwNam(native); /* INTL: Native. */ + native = Tcl_UtfToExternalDString(NULL, name, -1, &ds); + pwPtr = getpwnam(native); /* INTL: Native. */ Tcl_DStringFree(&ds); - + if (pwPtr == NULL) { + endpwent(); return NULL; } Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr); + endpwent(); return Tcl_DStringValue(bufferPtr); } @@ -628,17 +527,17 @@ TclpGetUserHome( *--------------------------------------------------------------------------- */ -int -TclpObjAccess( - Tcl_Obj *pathPtr, /* Path of file to access */ - int mode) /* Permission setting. */ +int +TclpObjAccess(pathPtr, mode) + Tcl_Obj *pathPtr; /* Path of file to access */ + int mode; /* Permission setting. */ { - const char *path = Tcl_FSGetNativePath(pathPtr); - + CONST char *path = Tcl_FSGetNativePath(pathPtr); if (path == NULL) { return -1; + } else { + return access(path, mode); } - return access(path, mode); } /* @@ -652,21 +551,21 @@ TclpObjAccess( * See chdir() documentation. * * Side effects: - * See chdir() documentation. + * See chdir() documentation. * *--------------------------------------------------------------------------- */ -int -TclpObjChdir( - Tcl_Obj *pathPtr) /* Path to new working directory */ +int +TclpObjChdir(pathPtr) + Tcl_Obj *pathPtr; /* Path to new working directory */ { - const char *path = Tcl_FSGetNativePath(pathPtr); - + CONST char *path = Tcl_FSGetNativePath(pathPtr); if (path == NULL) { return -1; + } else { + return chdir(path); } - return chdir(path); } /* @@ -685,10 +584,10 @@ TclpObjChdir( *---------------------------------------------------------------------- */ -int -TclpObjLstat( - Tcl_Obj *pathPtr, /* Path of file to stat */ - Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */ +int +TclpObjLstat(pathPtr, bufPtr) + Tcl_Obj *pathPtr; /* Path of file to stat */ + Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */ { return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr); } @@ -696,17 +595,17 @@ TclpObjLstat( /* *--------------------------------------------------------------------------- * - * TclpGetNativeCwd -- + * TclpObjGetCwd -- * * This function replaces the library version of getcwd(). * * Results: - * The input and output are filesystem paths in native form. The result - * is either the given clientData, if the working directory hasn't - * changed, or a new clientData (owned by our caller), giving the new - * native path, or NULL if the current directory could not be determined. - * If NULL is returned, the caller can examine the standard posix error - * codes to determine the cause of the problem. + * The result is a pointer to a string specifying the current + * directory, or NULL if the current directory could not be + * determined. If NULL is returned, an error message is left in the + * interp's result. 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. @@ -714,76 +613,39 @@ TclpObjLstat( *---------------------------------------------------------------------- */ -ClientData -TclpGetNativeCwd( - ClientData clientData) +Tcl_Obj* +TclpObjGetCwd(interp) + Tcl_Interp *interp; { - char buffer[MAXPATHLEN+1]; - -#ifdef USEGETWD - if (getwd(buffer) == NULL) { /* INTL: Native. */ - return NULL; - } -#else - if (getcwd(buffer, MAXPATHLEN+1) == NULL) { /* INTL: Native. */ + Tcl_DString ds; + if (TclpGetCwd(interp, &ds) != NULL) { + Tcl_Obj *cwdPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1); + Tcl_IncrRefCount(cwdPtr); + Tcl_DStringFree(&ds); + return cwdPtr; + } else { return NULL; } -#endif - - if ((clientData == NULL) || strcmp(buffer, (const char*)clientData)) { - char *newCd = ckalloc(strlen(buffer) + 1); - - strcpy(newCd, buffer); - return newCd; - } - - /* - * No change to pwd. - */ - - return clientData; } - -/* - *--------------------------------------------------------------------------- - * - * TclpGetCwd -- - * - * This function replaces the library version of getcwd(). (Obsolete - * function, only retained for old extensions which may call it - * directly). - * - * Results: - * The result is a pointer to a string specifying the current directory, - * or NULL if the current directory could not be determined. If NULL is - * returned, an error message is left in the interp's result. 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. - * - *---------------------------------------------------------------------- - */ -const char * -TclpGetCwd( - Tcl_Interp *interp, /* If non-NULL, used for error reporting. */ - Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with - * name of current directory. */ +/* Older string based version */ +CONST char * +TclpGetCwd(interp, bufferPtr) + Tcl_Interp *interp; /* If non-NULL, used for error reporting. */ + Tcl_DString *bufferPtr; /* Uninitialized or free DString filled + * with name of current directory. */ { char buffer[MAXPATHLEN+1]; #ifdef USEGETWD - if (getwd(buffer) == NULL) /* INTL: Native. */ + if (getwd(buffer) == NULL) { /* INTL: Native. */ #else - if (getcwd(buffer, MAXPATHLEN+1) == NULL) /* INTL: Native. */ + if (getcwd(buffer, MAXPATHLEN + 1) == NULL) { /* INTL: Native. */ #endif - { if (interp != NULL) { Tcl_AppendResult(interp, "error getting working directory name: ", - Tcl_PosixError(interp), NULL); + Tcl_PosixError(interp), (char *) NULL); } return NULL; } @@ -798,11 +660,11 @@ TclpGetCwd( * 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. + * 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. @@ -811,21 +673,21 @@ TclpGetCwd( */ char * -TclpReadlink( - const char *path, /* Path of file to readlink (UTF-8). */ - Tcl_DString *linkPtr) /* Uninitialized or free DString filled with - * contents of link (UTF-8). */ +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). */ { #ifndef DJGPP char link[MAXPATHLEN]; int length; - const char *native; + CONST char *native; Tcl_DString ds; native = Tcl_UtfToExternalDString(NULL, path, -1, &ds); length = readlink(native, link, sizeof(link)); /* INTL: Native. */ Tcl_DStringFree(&ds); - + if (length < 0) { return NULL; } @@ -853,318 +715,115 @@ TclpReadlink( *---------------------------------------------------------------------- */ -int -TclpObjStat( - Tcl_Obj *pathPtr, /* Path of file to stat */ - Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */ +int +TclpObjStat(pathPtr, bufPtr) + Tcl_Obj *pathPtr; /* Path of file to stat */ + Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */ { - const char *path = Tcl_FSGetNativePath(pathPtr); - + CONST char *path = Tcl_FSGetNativePath(pathPtr); if (path == NULL) { return -1; + } else { + return TclOSstat(path, bufPtr); } - return TclOSstat(path, bufPtr); } + #ifdef S_IFLNK -Tcl_Obj* -TclpObjLink( - Tcl_Obj *pathPtr, - Tcl_Obj *toPtr, - int linkAction) +Tcl_Obj* +TclpObjLink(pathPtr, toPtr, linkAction) + Tcl_Obj *pathPtr; + Tcl_Obj *toPtr; + int linkAction; { if (toPtr != NULL) { - const char *src = Tcl_FSGetNativePath(pathPtr); - const char *target = NULL; - - if (src == NULL) { + CONST char *src = Tcl_FSGetNativePath(pathPtr); + CONST char *target = Tcl_FSGetNativePath(toPtr); + + if (src == NULL || target == NULL) { return NULL; } - - /* - * If we're making a symbolic link and the path is relative, then we - * must check whether it exists _relative_ to the directory in which - * the src is found (not relative to the current cwd which is just not - * relevant in this case). - * - * If we're making a hard link, then a relative path is just converted - * to absolute relative to the cwd. - */ - - if ((linkAction & TCL_CREATE_SYMBOLIC_LINK) - && (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) { - Tcl_Obj *dirPtr, *absPtr; - - dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME); - if (dirPtr == NULL) { - return NULL; - } - absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr); - Tcl_IncrRefCount(absPtr); - if (Tcl_FSAccess(absPtr, F_OK) == -1) { - Tcl_DecrRefCount(absPtr); - Tcl_DecrRefCount(dirPtr); - - /* - * Target doesn't exist. - */ - - errno = ENOENT; - return NULL; - } - - /* - * Target exists; we'll construct the relative path we want below. - */ - - Tcl_DecrRefCount(absPtr); - Tcl_DecrRefCount(dirPtr); - } else { - target = Tcl_FSGetNativePath(toPtr); - if (target == NULL) { - return NULL; - } - if (access(target, F_OK) == -1) { - /* - * Target doesn't exist. - */ - - errno = ENOENT; - return NULL; - } - } - if (access(src, F_OK) != -1) { - /* - * Src exists. - */ - + /* src exists */ errno = EEXIST; return NULL; } - - /* - * Check symbolic link flag first, since we prefer to create these. + if (access(target, F_OK) == -1) { + /* target doesn't exist */ + errno = ENOENT; + return NULL; + } + /* + * Check symbolic link flag first, since we prefer to + * create these. */ - if (linkAction & TCL_CREATE_SYMBOLIC_LINK) { - int targetLen; - Tcl_DString ds; - Tcl_Obj *transPtr; - - /* - * Now we don't want to link to the absolute, normalized path. - * Relative links are quite acceptable (but links to ~user are not - * -- these must be expanded first). - */ - - transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr); - if (transPtr == NULL) { - return NULL; - } - target = Tcl_GetStringFromObj(transPtr, &targetLen); - target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds); - Tcl_DecrRefCount(transPtr); - - if (symlink(target, src) != 0) { - toPtr = NULL; - } - Tcl_DStringFree(&ds); + if (symlink(target, src) != 0) return NULL; } else if (linkAction & TCL_CREATE_HARD_LINK) { - if (link(target, src) != 0) { - return NULL; - } + if (link(target, src) != 0) return NULL; } else { errno = ENODEV; return NULL; } return toPtr; } else { - Tcl_Obj *linkPtr = NULL; + Tcl_Obj* linkPtr = NULL; char link[MAXPATHLEN]; int length; Tcl_DString ds; Tcl_Obj *transPtr; - + transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr); if (transPtr == NULL) { return NULL; } Tcl_DecrRefCount(transPtr); - + length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link)); if (length < 0) { return NULL; } Tcl_ExternalToUtfDString(NULL, link, length, &ds); - linkPtr = TclDStringToObj(&ds); - Tcl_IncrRefCount(linkPtr); + linkPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + if (linkPtr != NULL) { + Tcl_IncrRefCount(linkPtr); + } return linkPtr; } } -#endif /* S_IFLNK */ - -/* - *--------------------------------------------------------------------------- - * - * TclpFilesystemPathType -- - * - * This function is part of the native filesystem support, and returns - * the path type of the given path. Right now it simply returns NULL. In - * the future it could return specific path types, like 'nfs', 'samba', - * 'FAT32', etc. - * - * Results: - * NULL at present. - * - * Side effects: - * None. - * - *--------------------------------------------------------------------------- - */ -Tcl_Obj * -TclpFilesystemPathType( - Tcl_Obj *pathPtr) -{ - /* - * All native paths are of the same type. - */ +#endif - return NULL; -} /* *--------------------------------------------------------------------------- * - * TclpNativeToNormalized -- - * - * Convert native format to a normalized path object, with refCount of - * zero. + * TclpFilesystemPathType -- * - * Currently assumes all native paths are actually normalized already, so - * if the path given is not normalized this will actually just convert to - * a valid string path, but not necessarily a normalized one. + * This function is part of the native filesystem support, and + * returns the path type of the given path. Right now it simply + * returns NULL. In the future it could return specific path + * types, like 'nfs', 'samba', 'FAT32', etc. * * Results: - * A valid normalized path. + * NULL at present. * * Side effects: * None. * *--------------------------------------------------------------------------- */ - -Tcl_Obj * -TclpNativeToNormalized( - ClientData clientData) -{ - Tcl_DString ds; - - Tcl_ExternalToUtfDString(NULL, (const char *) clientData, -1, &ds); - return TclDStringToObj(&ds); -} - -/* - *--------------------------------------------------------------------------- - * - * TclNativeCreateNativeRep -- - * - * Create a native representation for the given path. - * - * Results: - * The nativePath representation. - * - * Side effects: - * Memory will be allocated. The path may need to be normalized. - * - *--------------------------------------------------------------------------- - */ - -ClientData -TclNativeCreateNativeRep( - Tcl_Obj *pathPtr) -{ - char *nativePathPtr; - const char *str; - Tcl_DString ds; - Tcl_Obj *validPathPtr; - int len; - - if (TclFSCwdIsNative()) { - /* - * The cwd is native, which means we can use the translated path - * without worrying about normalization (this will also usually be - * shorter so the utf-to-external conversion will be somewhat faster). - */ - - validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr); - if (validPathPtr == NULL) { - return NULL; - } - } else { - /* - * Make sure the normalized path is set. - */ - - validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); - if (validPathPtr == NULL) { - return NULL; - } - Tcl_IncrRefCount(validPathPtr); - } - - str = Tcl_GetStringFromObj(validPathPtr, &len); - Tcl_UtfToExternalDString(NULL, str, len, &ds); - len = Tcl_DStringLength(&ds) + sizeof(char); - Tcl_DecrRefCount(validPathPtr); - nativePathPtr = ckalloc(len); - memcpy(nativePathPtr, Tcl_DStringValue(&ds), (size_t) len); - - Tcl_DStringFree(&ds); - return nativePathPtr; -} - -/* - *--------------------------------------------------------------------------- - * - * TclNativeDupInternalRep -- - * - * Duplicate the native representation. - * - * Results: - * The copied native representation, or NULL if it is not possible to - * copy the representation. - * - * Side effects: - * Memory will be allocated for the copy. - * - *--------------------------------------------------------------------------- - */ - -ClientData -TclNativeDupInternalRep( - ClientData clientData) +Tcl_Obj* +TclpFilesystemPathType(pathObjPtr) + Tcl_Obj* pathObjPtr; { - char *copy; - size_t len; - - if (clientData == NULL) { - return NULL; - } - - /* - * ASCII representation when running on Unix. - */ - - len = (strlen((const char*) clientData) + 1) * sizeof(char); - - copy = ckalloc(len); - memcpy(copy, clientData, len); - return copy; + /* All native paths are of the same type */ + return NULL; } /* @@ -1182,13 +841,12 @@ TclNativeDupInternalRep( * *--------------------------------------------------------------------------- */ - -int -TclpUtime( - Tcl_Obj *pathPtr, /* File to modify */ - struct utimbuf *tval) /* New modification date structure */ +int +TclpUtime(pathPtr, tval) + Tcl_Obj *pathPtr; /* File to modify */ + struct utimbuf *tval; /* New modification date structure */ { - return utime(Tcl_FSGetNativePath(pathPtr), tval); + return utime(Tcl_FSGetNativePath(pathPtr),tval); } #ifdef __CYGWIN__ int TclOSstat(const char *name, Tcl_StatBuf *statBuf) { |