4 * This file contains wrappers around UNIX file handling functions.
5 * These wrappers mask differences between Windows and UNIX.
7 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
9 * See the file "license.terms" for information on usage and redistribution
10 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 #include "tclFileSystem.h"
16 static int NativeMatchType(Tcl_Interp *interp, const char* nativeEntry,
17 const char* nativeName, Tcl_GlobTypeData *types);
20 *---------------------------------------------------------------------------
22 * TclpFindExecutable --
24 * This function computes the absolute path name of the current
25 * application, given its argv[0] value. For Cygwin, argv[0] is
26 * ignored and the path is determined the same as under win32.
32 * The computed path name is stored as a ProcessGlobalValue.
34 *---------------------------------------------------------------------------
39 const char *argv0) /* The value of the application's argv[0]
42 Tcl_Encoding encoding;
45 wchar_t buf[PATH_MAX] = L"";
46 char name[PATH_MAX * 3 + 1];
48 GetModuleFileNameW(NULL, buf, PATH_MAX);
49 cygwin_conv_path(3, buf, name, sizeof(name));
50 length = strlen(name);
51 if ((length > 4) && !strcasecmp(name + length - 4, ".exe")) {
52 /* Strip '.exe' part. */
55 encoding = Tcl_GetEncoding(NULL, NULL);
56 TclSetObjNameOfExecutable(
57 Tcl_NewStringObj(name, length), encoding);
61 Tcl_DString buffer, nameString, cwd, utfName;
66 Tcl_DStringInit(&buffer);
69 for (p = name; *p != '\0'; p++) {
72 * The name contains a slash, so use the name directly without
73 * doing a path search.
80 p = getenv("PATH"); /* INTL: Native. */
83 * There's no PATH environment variable; use the default that is used
88 } else if (*p == '\0') {
90 * An empty path is equivalent to ".".
97 * Search through all the directories named in the PATH variable to see if
98 * argv[0] is in one of them. If so, use that file name.
102 while (TclIsSpaceProcM(*p)) {
106 while ((*p != ':') && (*p != 0)) {
109 TclDStringClear(&buffer);
111 Tcl_DStringAppend(&buffer, name, p - name);
113 TclDStringAppendLiteral(&buffer, "/");
116 name = Tcl_DStringAppend(&buffer, argv0, -1);
119 * INTL: The following calls to access() and stat() should not be
120 * converted to Tclp routines because they need to operate on native
124 if ((access(name, X_OK) == 0) /* INTL: Native. */
125 && (TclOSstat(name, &statBuf) == 0) /* INTL: Native. */
126 && S_ISREG(statBuf.st_mode)) {
131 } else if (*(p+1) == 0) {
137 TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
141 * If the name starts with "/" then just store it
151 encoding = Tcl_GetEncoding(NULL, NULL);
152 Tcl_ExternalToUtfDString(encoding, name, -1, &utfName);
153 TclSetObjNameOfExecutable(
154 Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
155 Tcl_DStringFree(&utfName);
159 if (TclpGetCwd(NULL, &cwd) == NULL) {
160 TclSetObjNameOfExecutable(Tcl_NewObj(), NULL);
165 * The name is relative to the current working directory. First strip off
166 * a leading "./", if any, then add the full path name of the current
170 if ((name[0] == '.') && (name[1] == '/')) {
174 Tcl_DStringInit(&nameString);
175 Tcl_DStringAppend(&nameString, name, -1);
177 Tcl_DStringFree(&buffer);
178 Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
179 Tcl_DStringLength(&cwd), &buffer);
180 if (Tcl_DStringValue(&cwd)[Tcl_DStringLength(&cwd) -1] != '/') {
181 TclDStringAppendLiteral(&buffer, "/");
183 Tcl_DStringFree(&cwd);
184 TclDStringAppendDString(&buffer, &nameString);
185 Tcl_DStringFree(&nameString);
187 encoding = Tcl_GetEncoding(NULL, NULL);
188 Tcl_ExternalToUtfDString(encoding, Tcl_DStringValue(&buffer), -1,
190 TclSetObjNameOfExecutable(
191 Tcl_NewStringObj(Tcl_DStringValue(&utfName), -1), encoding);
192 Tcl_DStringFree(&utfName);
195 Tcl_DStringFree(&buffer);
200 *----------------------------------------------------------------------
202 * TclpMatchInDirectory --
204 * This routine is used by the globbing code to search a directory for
205 * all files which match a given pattern.
208 * The return value is a standard Tcl result indicating whether an error
209 * occurred in globbing. Errors are left in interp, good results are
210 * [lappend]ed to resultPtr (which must be a valid object).
215 *----------------------------------------------------------------------
219 TclpMatchInDirectory(
220 Tcl_Interp *interp, /* Interpreter to receive errors. */
221 Tcl_Obj *resultPtr, /* List object to lappend results. */
222 Tcl_Obj *pathPtr, /* Contains path to directory to search. */
223 const char *pattern, /* Pattern to match against. */
224 Tcl_GlobTypeData *types) /* Object containing list of acceptable types.
225 * May be NULL. In particular the directory
226 * flag is very important. */
229 Tcl_Obj *fileNamePtr;
232 if (types != NULL && types->type == TCL_GLOB_TYPE_MOUNT) {
234 * The native filesystem never adds mounts.
240 fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
241 if (fileNamePtr == NULL) {
245 if (pattern == NULL || (*pattern == '\0')) {
247 * Match a file directly.
251 const char *nativeTail;
253 native = (const char *)Tcl_FSGetNativePath(pathPtr);
254 tailPtr = TclPathPart(interp, pathPtr, TCL_PATH_TAIL);
255 nativeTail = (const char *)Tcl_FSGetNativePath(tailPtr);
256 matchResult = NativeMatchType(interp, native, nativeTail, types);
257 if (matchResult == 1) {
258 Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
260 Tcl_DecrRefCount(tailPtr);
261 Tcl_DecrRefCount(fileNamePtr);
264 Tcl_DirEntry *entryPtr;
266 int dirLength, nativeDirLen;
267 int matchHidden, matchHiddenPat;
269 Tcl_DString ds; /* native encoding of dir */
270 Tcl_DString dsOrig; /* utf-8 encoding of dir */
272 Tcl_DStringInit(&dsOrig);
273 dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength);
274 Tcl_DStringAppend(&dsOrig, dirName, dirLength);
277 * Make sure that the directory part of the name really is a
278 * directory. If the directory name is "", use the name "." instead,
279 * because some UNIX systems don't treat "" like "." automatically.
280 * Keep the "" for use in generating file names, otherwise "glob
281 * foo.c" would return "./foo.c".
284 if (dirLength == 0) {
287 dirName = Tcl_DStringValue(&dsOrig);
290 * Make sure we have a trailing directory delimiter.
293 if (dirName[dirLength-1] != '/') {
294 dirName = TclDStringAppendLiteral(&dsOrig, "/");
300 * Now open the directory for reading and iterate over the contents.
303 native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
305 if ((TclOSstat(native, &statBuf) != 0) /* INTL: Native. */
306 || !S_ISDIR(statBuf.st_mode)) {
307 Tcl_DStringFree(&dsOrig);
308 Tcl_DStringFree(&ds);
309 Tcl_DecrRefCount(fileNamePtr);
313 d = TclOSopendir(native); /* INTL: Native. */
315 Tcl_DStringFree(&ds);
316 if (interp != NULL) {
317 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
318 "couldn't read directory \"%s\": %s",
319 Tcl_DStringValue(&dsOrig), Tcl_PosixError(interp)));
321 Tcl_DStringFree(&dsOrig);
322 Tcl_DecrRefCount(fileNamePtr);
326 nativeDirLen = Tcl_DStringLength(&ds);
329 * Check to see if -type or the pattern requests hidden files.
332 matchHiddenPat = (pattern[0] == '.')
333 || ((pattern[0] == '\\') && (pattern[1] == '.'));
334 matchHidden = matchHiddenPat
335 || (types && (types->perm & TCL_GLOB_PERM_HIDDEN));
336 while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */
341 * Skip this file if it doesn't agree with the hidden parameters
342 * requested by the user (via -type or pattern).
345 if (*entryPtr->d_name == '.') {
351 if (matchHiddenPat) {
354 /* Also need to check HFS hidden flag in TclMacOSXMatchType. */
363 * Now check to see if the file matches, according to both type
364 * and pattern. If so, add the file to the result.
367 utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name, -1,
369 if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
373 Tcl_DStringSetLength(&ds, nativeDirLen);
374 native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
375 matchResult = NativeMatchType(interp, native,
376 entryPtr->d_name, types);
377 typeOk = (matchResult == 1);
380 Tcl_ListObjAppendElement(interp, resultPtr,
381 TclNewFSPathObj(pathPtr, utfname,
382 Tcl_DStringLength(&utfDs)));
385 Tcl_DStringFree(&utfDs);
386 if (matchResult < 0) {
392 Tcl_DStringFree(&ds);
393 Tcl_DStringFree(&dsOrig);
394 Tcl_DecrRefCount(fileNamePtr);
396 if (matchResult < 0) {
403 *----------------------------------------------------------------------
407 * This routine is used by the globbing code to check if a file matches a
408 * given type description.
411 * The return value is 1, 0 or -1 indicating whether the file matches the
412 * given criteria, does not match them, or an error occurred (in which
413 * case an error is left in interp).
418 *----------------------------------------------------------------------
423 Tcl_Interp *interp, /* Interpreter to receive errors. */
424 const char *nativeEntry, /* Native path to check. */
425 const char *nativeName, /* Native filename to check. */
426 Tcl_GlobTypeData *types) /* Type description to match against. */
432 * Simply check for the file's existence, but do it with lstat, in
433 * case it is a link to a file which doesn't exist (since that case
434 * would not show up if we used 'access' or 'stat')
437 if (TclOSlstat(nativeEntry, &buf) != 0) {
443 if (types->perm != 0) {
444 if (TclOSstat(nativeEntry, &buf) != 0) {
446 * Either the file has disappeared between the 'readdir' call and
447 * the 'stat' call, or the file is a link to a file which doesn't
448 * exist (which we could ascertain with lstat), or there is some
449 * other strange problem. In all these cases, we define this to
450 * mean the file does not match any defined permission, and
451 * therefore it is not added to the list of files to return.
458 * readonly means that there are NO write permissions (even for user),
459 * but execute is OK for anybody OR that the user immutable flag is
460 * set (where supported).
463 if (((types->perm & TCL_GLOB_PERM_RONLY) &&
464 #if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
465 !(buf.st_flags & UF_IMMUTABLE) &&
467 (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
468 ((types->perm & TCL_GLOB_PERM_R) &&
469 (access(nativeEntry, R_OK) != 0)) ||
470 ((types->perm & TCL_GLOB_PERM_W) &&
471 (access(nativeEntry, W_OK) != 0)) ||
472 ((types->perm & TCL_GLOB_PERM_X) &&
473 (access(nativeEntry, X_OK) != 0))
475 || ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
476 (*nativeName != '.'))
477 #endif /* MAC_OSX_TCL */
482 if (types->type != 0) {
483 if (types->perm == 0) {
485 * We haven't yet done a stat on the file.
488 if (TclOSstat(nativeEntry, &buf) != 0) {
490 * Posix error occurred. The only ok case is if this is a link
491 * to a nonexistent file, and the user did 'glob -l'. So we
495 if ((types->type & TCL_GLOB_TYPE_LINK)
496 && (TclOSlstat(nativeEntry, &buf) == 0)
497 && S_ISLNK(buf.st_mode)) {
505 * In order bcdpsfl as in 'find -t'
508 if ( ((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) ||
509 ((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) ||
510 ((types->type & TCL_GLOB_TYPE_DIR) && S_ISDIR(buf.st_mode)) ||
511 ((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))||
513 ((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))||
514 #endif /* S_ISSOCK */
515 ((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))) {
517 * Do nothing - this file is ok.
521 if ((types->type & TCL_GLOB_TYPE_LINK)
522 && (TclOSlstat(nativeEntry, &buf) == 0)
523 && S_ISLNK(buf.st_mode)) {
533 * If we're on OSX, we also have to worry about matching the file creator
534 * code (if specified). Do that now.
538 if (types->macType != NULL || types->macCreator != NULL ||
539 (types->perm & TCL_GLOB_PERM_HIDDEN)) {
542 if (types->perm == 0 && types->type == 0) {
544 * We haven't yet done a stat on the file.
547 if (TclOSstat(nativeEntry, &buf) != 0) {
552 matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName,
554 if (matchResult != 1) {
558 #endif /* MAC_OSX_TCL */
564 *---------------------------------------------------------------------------
568 * This function takes the specified user name and finds their home
572 * The result is a pointer to a string specifying the user's home
573 * directory, or NULL if the user's home directory could not be
574 * determined. Storage for the result string is allocated in bufferPtr;
575 * the caller must call Tcl_DStringFree() when the result is no longer
581 *----------------------------------------------------------------------
586 const char *name, /* User name for desired home directory. */
587 Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
588 * name of user's home directory. */
590 struct passwd *pwPtr;
592 const char *native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);
594 pwPtr = TclpGetPwNam(native); /* INTL: Native. */
595 Tcl_DStringFree(&ds);
600 Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
601 return Tcl_DStringValue(bufferPtr);
605 *---------------------------------------------------------------------------
609 * This function replaces the library version of access().
612 * See access() documentation.
615 * See access() documentation.
617 *---------------------------------------------------------------------------
622 Tcl_Obj *pathPtr, /* Path of file to access */
623 int mode) /* Permission setting. */
625 const char *path = Tcl_FSGetNativePath(pathPtr);
630 return access(path, mode);
634 *---------------------------------------------------------------------------
638 * This function replaces the library version of chdir().
641 * See chdir() documentation.
644 * See chdir() documentation.
646 *---------------------------------------------------------------------------
651 Tcl_Obj *pathPtr) /* Path to new working directory */
653 const char *path = (const char *)Tcl_FSGetNativePath(pathPtr);
662 *----------------------------------------------------------------------
666 * This function replaces the library version of lstat().
669 * See lstat() documentation.
672 * See lstat() documentation.
674 *----------------------------------------------------------------------
679 Tcl_Obj *pathPtr, /* Path of file to stat */
680 Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
682 return TclOSlstat((const char *)Tcl_FSGetNativePath(pathPtr), bufPtr);
686 *---------------------------------------------------------------------------
688 * TclpGetNativeCwd --
690 * This function replaces the library version of getcwd().
693 * The input and output are filesystem paths in native form. The result
694 * is either the given clientData, if the working directory hasn't
695 * changed, or a new clientData (owned by our caller), giving the new
696 * native path, or NULL if the current directory could not be determined.
697 * If NULL is returned, the caller can examine the standard posix error
698 * codes to determine the cause of the problem.
703 *----------------------------------------------------------------------
708 ClientData clientData)
710 char buffer[MAXPATHLEN+1];
713 if (getwd(buffer) == NULL) { /* INTL: Native. */
717 if (getcwd(buffer, MAXPATHLEN+1) == NULL) { /* INTL: Native. */
720 #endif /* USEGETWD */
722 if ((clientData == NULL) || strcmp(buffer, (const char *) clientData)) {
723 char *newCd = (char*)ckalloc(strlen(buffer) + 1);
725 strcpy(newCd, buffer);
737 *---------------------------------------------------------------------------
741 * This function replaces the library version of getcwd(). (Obsolete
742 * function, only retained for old extensions which may call it
746 * The result is a pointer to a string specifying the current directory,
747 * or NULL if the current directory could not be determined. If NULL is
748 * returned, an error message is left in the interp's result. Storage for
749 * the result string is allocated in bufferPtr; the caller must call
750 * Tcl_DStringFree() when the result is no longer needed.
755 *----------------------------------------------------------------------
760 Tcl_Interp *interp, /* If non-NULL, used for error reporting. */
761 Tcl_DString *bufferPtr) /* Uninitialized or free DString filled with
762 * name of current directory. */
764 char buffer[MAXPATHLEN+1];
767 if (getwd(buffer) == NULL) /* INTL: Native. */
769 if (getcwd(buffer, MAXPATHLEN+1) == NULL) /* INTL: Native. */
770 #endif /* USEGETWD */
772 if (interp != NULL) {
773 Tcl_SetObjResult(interp, Tcl_ObjPrintf(
774 "error getting working directory name: %s",
775 Tcl_PosixError(interp)));
779 return Tcl_ExternalToUtfDString(NULL, buffer, -1, bufferPtr);
783 *---------------------------------------------------------------------------
787 * This function replaces the library version of readlink().
790 * The result is a pointer to a string specifying the contents of the
791 * symbolic link given by 'path', or NULL if the symbolic link could not
792 * be read. Storage for the result string is allocated in bufferPtr; the
793 * caller must call Tcl_DStringFree() when the result is no longer
797 * See readlink() documentation.
799 *---------------------------------------------------------------------------
804 const char *path, /* Path of file to readlink (UTF-8). */
805 Tcl_DString *linkPtr) /* Uninitialized or free DString filled with
806 * contents of link (UTF-8). */
809 char link[MAXPATHLEN];
814 native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
815 length = readlink(native, link, sizeof(link)); /* INTL: Native. */
816 Tcl_DStringFree(&ds);
822 Tcl_ExternalToUtfDString(NULL, link, length, linkPtr);
823 return Tcl_DStringValue(linkPtr);
830 *----------------------------------------------------------------------
834 * This function replaces the library version of stat().
837 * See stat() documentation.
840 * See stat() documentation.
842 *----------------------------------------------------------------------
847 Tcl_Obj *pathPtr, /* Path of file to stat */
848 Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */
850 const char *path = (const char *)Tcl_FSGetNativePath(pathPtr);
855 return TclOSstat(path, bufPtr);
867 const char *src = (const char *)Tcl_FSGetNativePath(pathPtr);
868 const char *target = NULL;
875 * If we're making a symbolic link and the path is relative, then we
876 * must check whether it exists _relative_ to the directory in which
877 * the src is found (not relative to the current cwd which is just not
878 * relevant in this case).
880 * If we're making a hard link, then a relative path is just converted
881 * to absolute relative to the cwd.
884 if ((linkAction & TCL_CREATE_SYMBOLIC_LINK)
885 && (Tcl_FSGetPathType(toPtr) == TCL_PATH_RELATIVE)) {
886 Tcl_Obj *dirPtr, *absPtr;
888 dirPtr = TclPathPart(NULL, pathPtr, TCL_PATH_DIRNAME);
889 if (dirPtr == NULL) {
892 absPtr = Tcl_FSJoinToPath(dirPtr, 1, &toPtr);
893 Tcl_IncrRefCount(absPtr);
894 if (Tcl_FSAccess(absPtr, F_OK) == -1) {
895 Tcl_DecrRefCount(absPtr);
896 Tcl_DecrRefCount(dirPtr);
899 * Target doesn't exist.
907 * Target exists; we'll construct the relative path we want below.
910 Tcl_DecrRefCount(absPtr);
911 Tcl_DecrRefCount(dirPtr);
913 target = (const char*)Tcl_FSGetNativePath(toPtr);
914 if (target == NULL) {
917 if (access(target, F_OK) == -1) {
919 * Target doesn't exist.
927 if (access(src, F_OK) != -1) {
937 * Check symbolic link flag first, since we prefer to create these.
940 if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
946 * Now we don't want to link to the absolute, normalized path.
947 * Relative links are quite acceptable (but links to ~user are not
948 * -- these must be expanded first).
951 transPtr = Tcl_FSGetTranslatedPath(NULL, toPtr);
952 if (transPtr == NULL) {
955 target = Tcl_GetStringFromObj(transPtr, &targetLen);
956 target = Tcl_UtfToExternalDString(NULL, target, targetLen, &ds);
957 Tcl_DecrRefCount(transPtr);
959 if (symlink(target, src) != 0) {
962 Tcl_DStringFree(&ds);
963 } else if (linkAction & TCL_CREATE_HARD_LINK) {
964 if (link(target, src) != 0) {
973 Tcl_Obj *linkPtr = NULL;
975 char link[MAXPATHLEN];
980 transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
981 if (transPtr == NULL) {
984 Tcl_DecrRefCount(transPtr);
986 length = readlink((const char *)Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
991 Tcl_ExternalToUtfDString(NULL, link, length, &ds);
992 linkPtr = TclDStringToObj(&ds);
993 Tcl_IncrRefCount(linkPtr);
1000 *---------------------------------------------------------------------------
1002 * TclpFilesystemPathType --
1004 * This function is part of the native filesystem support, and returns
1005 * the path type of the given path. Right now it simply returns NULL. In
1006 * the future it could return specific path types, like 'nfs', 'samba',
1015 *---------------------------------------------------------------------------
1019 TclpFilesystemPathType(
1023 * All native paths are of the same type.
1030 *---------------------------------------------------------------------------
1032 * TclpNativeToNormalized --
1034 * Convert native format to a normalized path object, with refCount of
1037 * Currently assumes all native paths are actually normalized already, so
1038 * if the path given is not normalized this will actually just convert to
1039 * a valid string path, but not necessarily a normalized one.
1042 * A valid normalized path.
1047 *---------------------------------------------------------------------------
1051 TclpNativeToNormalized(
1052 ClientData clientData)
1056 Tcl_ExternalToUtfDString(NULL, (const char *) clientData, -1, &ds);
1057 return TclDStringToObj(&ds);
1061 *---------------------------------------------------------------------------
1063 * TclNativeCreateNativeRep --
1065 * Create a native representation for the given path.
1068 * The nativePath representation.
1071 * Memory will be allocated. The path may need to be normalized.
1073 *---------------------------------------------------------------------------
1077 TclNativeCreateNativeRep(
1080 char *nativePathPtr;
1083 Tcl_Obj *validPathPtr;
1086 if (TclFSCwdIsNative()) {
1088 * The cwd is native, which means we can use the translated path
1089 * without worrying about normalization (this will also usually be
1090 * shorter so the utf-to-external conversion will be somewhat faster).
1093 validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
1094 if (validPathPtr == NULL) {
1099 * Make sure the normalized path is set.
1102 validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr);
1103 if (validPathPtr == NULL) {
1106 Tcl_IncrRefCount(validPathPtr);
1109 str = Tcl_GetStringFromObj(validPathPtr, &len);
1110 Tcl_UtfToExternalDString(NULL, str, len, &ds);
1111 len = Tcl_DStringLength(&ds) + sizeof(char);
1112 if (strlen(Tcl_DStringValue(&ds)) < len - sizeof(char)) {
1113 /* See bug [3118489]: NUL in filenames */
1114 Tcl_DecrRefCount(validPathPtr);
1115 Tcl_DStringFree(&ds);
1118 Tcl_DecrRefCount(validPathPtr);
1119 nativePathPtr = (char *)ckalloc(len);
1120 memcpy(nativePathPtr, Tcl_DStringValue(&ds), len);
1122 Tcl_DStringFree(&ds);
1123 return nativePathPtr;
1127 *---------------------------------------------------------------------------
1129 * TclNativeDupInternalRep --
1131 * Duplicate the native representation.
1134 * The copied native representation, or NULL if it is not possible to
1135 * copy the representation.
1138 * Memory will be allocated for the copy.
1140 *---------------------------------------------------------------------------
1144 TclNativeDupInternalRep(
1145 ClientData clientData)
1150 if (clientData == NULL) {
1155 * ASCII representation when running on Unix.
1158 len = (strlen((const char*) clientData) + 1) * sizeof(char);
1160 copy = (char *)ckalloc(len);
1161 memcpy(copy, clientData, len);
1166 *---------------------------------------------------------------------------
1170 * Set the modification date for a file.
1173 * 0 on success, -1 on error.
1178 *---------------------------------------------------------------------------
1183 Tcl_Obj *pathPtr, /* File to modify */
1184 struct utimbuf *tval) /* New modification date structure */
1186 return utime((const char *)Tcl_FSGetNativePath(pathPtr), tval);
1197 Tcl_StatBuf *statBuf = (Tcl_StatBuf *)cygstat;
1198 int result = stat(name, &buf);
1200 statBuf->st_mode = buf.st_mode;
1201 statBuf->st_ino = buf.st_ino;
1202 statBuf->st_dev = buf.st_dev;
1203 statBuf->st_rdev = buf.st_rdev;
1204 statBuf->st_nlink = buf.st_nlink;
1205 statBuf->st_uid = buf.st_uid;
1206 statBuf->st_gid = buf.st_gid;
1207 statBuf->st_size = buf.st_size;
1208 statBuf->st_atime = buf.st_atime;
1209 statBuf->st_mtime = buf.st_mtime;
1210 statBuf->st_ctime = buf.st_ctime;
1220 Tcl_StatBuf *statBuf = (Tcl_StatBuf *)cygstat;
1221 int result = lstat(name, &buf);
1223 statBuf->st_mode = buf.st_mode;
1224 statBuf->st_ino = buf.st_ino;
1225 statBuf->st_dev = buf.st_dev;
1226 statBuf->st_rdev = buf.st_rdev;
1227 statBuf->st_nlink = buf.st_nlink;
1228 statBuf->st_uid = buf.st_uid;
1229 statBuf->st_gid = buf.st_gid;
1230 statBuf->st_size = buf.st_size;
1231 statBuf->st_atime = buf.st_atime;
1232 statBuf->st_mtime = buf.st_mtime;
1233 statBuf->st_ctime = buf.st_ctime;