os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixFile.c
First public contribution.
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.
8 * Portions Copyright (c) 2007 Nokia Corporation and/or its subsidiaries. All rights reserved.
10 * See the file "license.terms" for information on usage and redistribution
11 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * RCS: @(#) $Id: tclUnixFile.c,v 1.32.2.2 2003/10/31 08:46:41 vincentdarley Exp $
18 #if defined(__SYMBIAN32__)
19 #include "convertPathSlashes.h"
20 #include "tclSymbianGlobals.h"
23 static int NativeMatchType(CONST char* nativeName, Tcl_GlobTypeData *types);
27 *---------------------------------------------------------------------------
29 * TclpFindExecutable --
31 * This procedure computes the absolute path name of the current
32 * application, given its argv[0] value.
35 * A dirty UTF string that is the path to the executable. At this
36 * point we may not know the system encoding. Convert the native
37 * string value to UTF using the default encoding. The assumption
38 * is that we will still be able to parse the path given the path
39 * name contains ASCII string and '/' chars do not conflict with
43 * The variable tclNativeExecutableName gets filled in with the file
44 * name for the application, if we figured it out. If we couldn't
45 * figure it out, tclNativeExecutableName is set to NULL.
47 *---------------------------------------------------------------------------
51 TclpFindExecutable(argv0)
52 CONST char *argv0; /* The value of the application's argv[0]
58 Tcl_DString buffer, nameString;
66 if (tclNativeExecutableName != NULL) {
67 return tclNativeExecutableName;
71 // assuming if we're not using eshell that we have to specify the path.
73 if (!strstr(argv0, "Z:\\sys\\bin")) {
74 Tcl_DStringInit(&buffer);
75 Tcl_DStringSetLength(&buffer, 0);
76 Tcl_DStringAppend(&buffer, "Z:\\sys\\bin\\", 11);
77 name = Tcl_DStringAppend(&buffer, argv0, -1);
81 name = argv0; //use if we don't have to specify the path.
83 tclNativeExecutableName = ckalloc((unsigned) (strlen(name) + 1));
84 strcpy(tclNativeExecutableName, name);
86 tclCopySymbianPathSlashConversion(TO_TCL, tclNativeExecutableName, tclNativeExecutableName);
89 Tcl_DStringFree(&buffer);
92 return tclNativeExecutableName;
96 Tcl_DStringInit(&buffer);
99 for (p = name; *p != '\0'; p++) {
102 * The name contains a slash, so use the name directly
103 * without doing a path search.
110 p = getenv("PATH"); /* INTL: Native. */
113 * There's no PATH environment variable; use the default that
117 p = ":/bin:/usr/bin";
118 } else if (*p == '\0') {
120 * An empty path is equivalent to ".".
127 * Search through all the directories named in the PATH variable
128 * to see if argv[0] is in one of them. If so, use that file
133 while (isspace(UCHAR(*p))) { /* INTL: BUG */
137 while ((*p != ':') && (*p != 0)) {
140 Tcl_DStringSetLength(&buffer, 0);
142 Tcl_DStringAppend(&buffer, name, p - name);
144 Tcl_DStringAppend(&buffer, "/", 1);
147 name = Tcl_DStringAppend(&buffer, argv0, -1);
150 * INTL: The following calls to access() and stat() should not be
151 * converted to Tclp routines because they need to operate on native
155 if ((access(name, X_OK) == 0) /* INTL: Native. */
156 && (TclOSstat(name, &statBuf) == 0) /* INTL: Native. */
157 && S_ISREG(statBuf.st_mode)) {
162 } else if (*(p+1) == 0) {
171 * If the name starts with "/" then just copy it to tclExecutableName.
176 if (name[1] == ':') {
178 if (name[0] == '/') {
180 Tcl_ExternalToUtfDString(NULL, name, -1, &nameString);
181 tclNativeExecutableName = (char *)
182 ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1));
183 strcpy(tclNativeExecutableName, Tcl_DStringValue(&nameString));
184 Tcl_DStringFree(&nameString);
189 * The name is relative to the current working directory. First
190 * strip off a leading "./", if any, then add the full path name of
191 * the current working directory.
194 if ((name[0] == '.') && (name[1] == '/')) {
198 Tcl_ExternalToUtfDString(NULL, name, -1, &nameString);
200 Tcl_DStringFree(&buffer);
201 TclpGetCwd(NULL, &buffer);
203 length = Tcl_DStringLength(&buffer) + Tcl_DStringLength(&nameString) + 2;
204 tclNativeExecutableName = (char *) ckalloc((unsigned) length);
205 strcpy(tclNativeExecutableName, Tcl_DStringValue(&buffer));
206 tclNativeExecutableName[Tcl_DStringLength(&buffer)] = '/';
207 strcpy(tclNativeExecutableName + Tcl_DStringLength(&buffer) + 1,
208 Tcl_DStringValue(&nameString));
209 Tcl_DStringFree(&nameString);
214 Tcl_DStringFree(&buffer);
215 return tclNativeExecutableName;
219 *----------------------------------------------------------------------
221 * TclpMatchInDirectory --
223 * This routine is used by the globbing code to search a
224 * directory for all files which match a given pattern.
227 * The return value is a standard Tcl result indicating whether an
228 * error occurred in globbing. Errors are left in interp, good
229 * results are lappended to resultPtr (which must be a valid object)
234 *---------------------------------------------------------------------- */
237 TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types)
238 Tcl_Interp *interp; /* Interpreter to receive errors. */
239 Tcl_Obj *resultPtr; /* List object to lappend results. */
240 Tcl_Obj *pathPtr; /* Contains path to directory to search. */
241 CONST char *pattern; /* Pattern to match against. */
242 Tcl_GlobTypeData *types; /* Object containing list of acceptable types.
243 * May be NULL. In particular the directory
244 * flag is very important. */
247 Tcl_Obj *fileNamePtr;
249 fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
250 if (fileNamePtr == NULL) {
254 if (pattern == NULL || (*pattern == '\0')) {
255 /* Match a file directly */
256 native = (CONST char*) Tcl_FSGetNativePath(pathPtr);
257 if (NativeMatchType(native, types)) {
258 Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
260 Tcl_DecrRefCount(fileNamePtr);
264 Tcl_DirEntry *entryPtr;
270 Tcl_DString ds; /* native encoding of dir */
271 Tcl_DString dsOrig; /* utf-8 encoding of dir */
273 Tcl_DStringInit(&dsOrig);
274 dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength);
275 Tcl_DStringAppend(&dsOrig, dirName, dirLength);
278 * Make sure that the directory part of the name really is a
279 * directory. If the directory name is "", use the name "."
280 * instead, because some UNIX systems don't treat "" like "."
281 * automatically. Keep the "" for use in generating file names,
282 * otherwise "glob foo.c" would return "./foo.c".
285 if (dirLength == 0) {
288 dirName = Tcl_DStringValue(&dsOrig);
289 /* Make sure we have a trailing directory delimiter */
290 if (dirName[dirLength-1] != '/') {
291 dirName = Tcl_DStringAppend(&dsOrig, "/", 1);
295 Tcl_DecrRefCount(fileNamePtr);
298 * Now open the directory for reading and iterate over the contents.
301 native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
303 if ((TclOSstat(native, &statBuf) != 0) /* INTL: Native. */
304 || !S_ISDIR(statBuf.st_mode)) {
305 Tcl_DStringFree(&dsOrig);
306 Tcl_DStringFree(&ds);
310 d = opendir(native); /* INTL: Native. */
312 Tcl_DStringFree(&ds);
313 Tcl_ResetResult(interp);
314 Tcl_AppendResult(interp, "couldn't read directory \"",
315 Tcl_DStringValue(&dsOrig), "\": ",
316 Tcl_PosixError(interp), (char *) NULL);
317 Tcl_DStringFree(&dsOrig);
321 nativeDirLen = Tcl_DStringLength(&ds);
324 * Check to see if -type or the pattern requests hidden files.
326 matchHidden = ((types && (types->perm & TCL_GLOB_PERM_HIDDEN)) ||
328 || ((pattern[0] == '\\') && (pattern[1] == '.'))));
330 while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */
335 * Skip this file if it doesn't agree with the hidden
336 * parameters requested by the user (via -type or pattern).
338 if (*entryPtr->d_name == '.') {
339 if (!matchHidden) continue;
341 if (matchHidden) continue;
345 * Now check to see if the file matches, according to both type
346 * and pattern. If so, add the file to the result.
349 utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name,
351 if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
355 Tcl_DStringSetLength(&ds, nativeDirLen);
356 native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
357 typeOk = NativeMatchType(native, types);
360 Tcl_ListObjAppendElement(interp, resultPtr,
361 TclNewFSPathObj(pathPtr, utfname,
362 Tcl_DStringLength(&utfDs)));
365 Tcl_DStringFree(&utfDs);
369 Tcl_DStringFree(&ds);
370 Tcl_DStringFree(&dsOrig);
376 CONST char* nativeEntry, /* Native path to check */
377 Tcl_GlobTypeData *types) /* Type description to match against */
382 * Simply check for the file's existence, but do it
383 * with lstat, in case it is a link to a file which
384 * doesn't exist (since that case would not show up
385 * if we used 'access' or 'stat')
387 if (TclOSlstat(nativeEntry, &buf) != 0) {
391 if (types->perm != 0) {
392 if (TclOSstat(nativeEntry, &buf) != 0) {
394 * Either the file has disappeared between the
395 * 'readdir' call and the 'stat' call, or
396 * the file is a link to a file which doesn't
397 * exist (which we could ascertain with
398 * lstat), or there is some other strange
399 * problem. In all these cases, we define this
400 * to mean the file does not match any defined
401 * permission, and therefore it is not
402 * added to the list of files to return.
408 * readonly means that there are NO write permissions
409 * (even for user), but execute is OK for anybody
411 if (((types->perm & TCL_GLOB_PERM_RONLY) &&
412 (buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
413 ((types->perm & TCL_GLOB_PERM_R) &&
414 (access(nativeEntry, R_OK) != 0)) ||
415 ((types->perm & TCL_GLOB_PERM_W) &&
416 (access(nativeEntry, W_OK) != 0)) ||
417 ((types->perm & TCL_GLOB_PERM_X) &&
418 (access(nativeEntry, X_OK) != 0))
423 if (types->type != 0) {
424 if (types->perm == 0) {
425 /* We haven't yet done a stat on the file */
426 if (TclOSstat(nativeEntry, &buf) != 0) {
428 * Posix error occurred. The only ok
429 * case is if this is a link to a nonexistent
430 * file, and the user did 'glob -l'. So
431 * we check that here:
433 if (types->type & TCL_GLOB_TYPE_LINK) {
434 if (TclOSlstat(nativeEntry, &buf) == 0) {
435 if (S_ISLNK(buf.st_mode)) {
444 * In order bcdpfls as in 'find -t'
447 ((types->type & TCL_GLOB_TYPE_BLOCK) &&
448 S_ISBLK(buf.st_mode)) ||
449 ((types->type & TCL_GLOB_TYPE_CHAR) &&
450 S_ISCHR(buf.st_mode)) ||
451 ((types->type & TCL_GLOB_TYPE_DIR) &&
452 S_ISDIR(buf.st_mode)) ||
453 ((types->type & TCL_GLOB_TYPE_PIPE) &&
454 S_ISFIFO(buf.st_mode)) ||
455 ((types->type & TCL_GLOB_TYPE_FILE) &&
456 S_ISREG(buf.st_mode))
458 || ((types->type & TCL_GLOB_TYPE_SOCK) &&
459 S_ISSOCK(buf.st_mode))
460 #endif /* S_ISSOCK */
462 /* Do nothing -- this file is ok */
465 if (types->type & TCL_GLOB_TYPE_LINK) {
466 if (TclOSlstat(nativeEntry, &buf) == 0) {
467 if (S_ISLNK(buf.st_mode)) {
481 *---------------------------------------------------------------------------
485 * This function takes the specified user name and finds their
489 * The result is a pointer to a string specifying the user's home
490 * directory, or NULL if the user's home directory could not be
491 * determined. Storage for the result string is allocated in
492 * bufferPtr; the caller must call Tcl_DStringFree() when the result
493 * is no longer needed.
498 *----------------------------------------------------------------------
502 TclpGetUserHome(name, bufferPtr)
503 CONST char *name; /* User name for desired home directory. */
504 Tcl_DString *bufferPtr; /* Uninitialized or free DString filled
505 * with name of user's home directory. */
507 struct passwd *pwPtr;
511 native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);
512 pwPtr = getpwnam(native); /* INTL: Native. */
513 Tcl_DStringFree(&ds);
519 Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
521 return Tcl_DStringValue(bufferPtr);
525 *---------------------------------------------------------------------------
529 * This function replaces the library version of access().
532 * See access() documentation.
535 * See access() documentation.
537 *---------------------------------------------------------------------------
541 TclpObjAccess(pathPtr, mode)
542 Tcl_Obj *pathPtr; /* Path of file to access */
543 int mode; /* Permission setting. */
545 CONST char *path = Tcl_FSGetNativePath(pathPtr);
549 return access(path, mode);
554 *---------------------------------------------------------------------------
558 * This function replaces the library version of chdir().
561 * See chdir() documentation.
564 * See chdir() documentation.
566 *---------------------------------------------------------------------------
570 TclpObjChdir(pathPtr)
571 Tcl_Obj *pathPtr; /* Path to new working directory */
573 CONST char *path = Tcl_FSGetNativePath(pathPtr);
582 *----------------------------------------------------------------------
586 * This function replaces the library version of lstat().
589 * See lstat() documentation.
592 * See lstat() documentation.
594 *----------------------------------------------------------------------
598 TclpObjLstat(pathPtr, bufPtr)
599 Tcl_Obj *pathPtr; /* Path of file to stat */
600 Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */
602 return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr);
606 *---------------------------------------------------------------------------
610 * This function replaces the library version of getcwd().
613 * The result is a pointer to a string specifying the current
614 * directory, or NULL if the current directory could not be
615 * determined. If NULL is returned, an error message is left in the
616 * interp's result. Storage for the result string is allocated in
617 * bufferPtr; the caller must call Tcl_DStringFree() when the result
618 * is no longer needed.
623 *----------------------------------------------------------------------
627 TclpObjGetCwd(interp)
631 if (TclpGetCwd(interp, &ds) != NULL) {
632 Tcl_Obj *cwdPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
633 Tcl_IncrRefCount(cwdPtr);
634 Tcl_DStringFree(&ds);
641 /* Older string based version */
643 TclpGetCwd(interp, bufferPtr)
644 Tcl_Interp *interp; /* If non-NULL, used for error reporting. */
645 Tcl_DString *bufferPtr; /* Uninitialized or free DString filled
646 * with name of current directory. */
648 char buffer[MAXPATHLEN+1];
651 if (getwd(buffer) == NULL) { /* INTL: Native. */
653 if (getcwd(buffer, MAXPATHLEN + 1) == NULL) { /* INTL: Native. */
655 if (interp != NULL) {
656 Tcl_AppendResult(interp,
657 "error getting working directory name: ",
658 Tcl_PosixError(interp), (char *) NULL);
662 /* TODO - the line bellow is a temporary patch. The defect number is: DEF116621. */
664 return Tcl_ExternalToUtfDString(NULL, buffer, -1, bufferPtr);
668 *---------------------------------------------------------------------------
672 * This function replaces the library version of readlink().
675 * The result is a pointer to a string specifying the contents
676 * of the symbolic link given by 'path', or NULL if the symbolic
677 * link could not be read. Storage for the result string is
678 * allocated in bufferPtr; the caller must call Tcl_DStringFree()
679 * when the result is no longer needed.
682 * See readlink() documentation.
684 *---------------------------------------------------------------------------
688 TclpReadlink(path, linkPtr)
689 CONST char *path; /* Path of file to readlink (UTF-8). */
690 Tcl_DString *linkPtr; /* Uninitialized or free DString filled
691 * with contents of link (UTF-8). */
694 char link[MAXPATHLEN];
699 native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
700 length = readlink(native, link, sizeof(link)); /* INTL: Native. */
701 Tcl_DStringFree(&ds);
707 Tcl_ExternalToUtfDString(NULL, link, length, linkPtr);
708 return Tcl_DStringValue(linkPtr);
715 *----------------------------------------------------------------------
719 * This function replaces the library version of stat().
722 * See stat() documentation.
725 * See stat() documentation.
727 *----------------------------------------------------------------------
731 TclpObjStat(pathPtr, bufPtr)
732 Tcl_Obj *pathPtr; /* Path of file to stat */
733 Tcl_StatBuf *bufPtr; /* Filled with results of stat call. */
735 CONST char *path = Tcl_FSGetNativePath(pathPtr);
739 return TclOSstat(path, bufPtr);
747 TclpObjLink(pathPtr, toPtr, linkAction)
753 CONST char *src = Tcl_FSGetNativePath(pathPtr);
754 CONST char *target = Tcl_FSGetNativePath(toPtr);
756 if (src == NULL || target == NULL) {
759 if (access(src, F_OK) != -1) {
764 if (access(target, F_OK) == -1) {
765 /* target doesn't exist */
770 * Check symbolic link flag first, since we prefer to
773 if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
774 if (symlink(target, src) != 0) return NULL;
775 } else if (linkAction & TCL_CREATE_HARD_LINK) {
776 if (link(target, src) != 0) return NULL;
783 Tcl_Obj* linkPtr = NULL;
785 char link[MAXPATHLEN];
790 transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
791 if (transPtr == NULL) {
794 Tcl_DecrRefCount(transPtr);
796 length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
801 Tcl_ExternalToUtfDString(NULL, link, length, &ds);
802 linkPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds),
803 Tcl_DStringLength(&ds));
804 Tcl_DStringFree(&ds);
805 if (linkPtr != NULL) {
806 Tcl_IncrRefCount(linkPtr);
816 *---------------------------------------------------------------------------
818 * TclpFilesystemPathType --
820 * This function is part of the native filesystem support, and
821 * returns the path type of the given path. Right now it simply
822 * returns NULL. In the future it could return specific path
823 * types, like 'nfs', 'samba', 'FAT32', etc.
831 *---------------------------------------------------------------------------
834 TclpFilesystemPathType(pathObjPtr)
837 /* All native paths are of the same type */
842 *---------------------------------------------------------------------------
846 * Set the modification date for a file.
849 * 0 on success, -1 on error.
854 *---------------------------------------------------------------------------
857 TclpUtime(pathPtr, tval)
858 Tcl_Obj *pathPtr; /* File to modify */
859 struct utimbuf *tval; /* New modification date structure */
861 return utime(Tcl_FSGetNativePath(pathPtr),tval);