os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/unix/tclUnixFile.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* 
sl@0
     2
 * tclUnixFile.c --
sl@0
     3
 *
sl@0
     4
 *      This file contains wrappers around UNIX file handling functions.
sl@0
     5
 *      These wrappers mask differences between Windows and UNIX.
sl@0
     6
 *
sl@0
     7
 * Copyright (c) 1995-1998 Sun Microsystems, Inc.
sl@0
     8
 * Portions Copyright (c) 2007 Nokia Corporation and/or its subsidiaries. All rights reserved.   
sl@0
     9
 *
sl@0
    10
 * See the file "license.terms" for information on usage and redistribution
sl@0
    11
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
sl@0
    12
 *
sl@0
    13
 * RCS: @(#) $Id: tclUnixFile.c,v 1.32.2.2 2003/10/31 08:46:41 vincentdarley Exp $
sl@0
    14
 */
sl@0
    15
sl@0
    16
#include "tclInt.h"
sl@0
    17
#include "tclPort.h"
sl@0
    18
#if defined(__SYMBIAN32__) 
sl@0
    19
#include "convertPathSlashes.h"
sl@0
    20
#include "tclSymbianGlobals.h"
sl@0
    21
#endif 
sl@0
    22
sl@0
    23
static int NativeMatchType(CONST char* nativeName, Tcl_GlobTypeData *types);
sl@0
    24
sl@0
    25

sl@0
    26
/*
sl@0
    27
 *---------------------------------------------------------------------------
sl@0
    28
 *
sl@0
    29
 * TclpFindExecutable --
sl@0
    30
 *
sl@0
    31
 *	This procedure computes the absolute path name of the current
sl@0
    32
 *	application, given its argv[0] value.
sl@0
    33
 *
sl@0
    34
 * Results:
sl@0
    35
 *	A dirty UTF string that is the path to the executable.  At this
sl@0
    36
 *	point we may not know the system encoding.  Convert the native
sl@0
    37
 *	string value to UTF using the default encoding.  The assumption
sl@0
    38
 *	is that we will still be able to parse the path given the path
sl@0
    39
 *	name contains ASCII string and '/' chars do not conflict with
sl@0
    40
 *	other UTF chars.
sl@0
    41
 *
sl@0
    42
 * Side effects:
sl@0
    43
 *	The variable tclNativeExecutableName gets filled in with the file
sl@0
    44
 *	name for the application, if we figured it out.  If we couldn't
sl@0
    45
 *	figure it out, tclNativeExecutableName is set to NULL.
sl@0
    46
 *
sl@0
    47
 *---------------------------------------------------------------------------
sl@0
    48
 */
sl@0
    49
sl@0
    50
char *
sl@0
    51
TclpFindExecutable(argv0)
sl@0
    52
    CONST char *argv0;		/* The value of the application's argv[0]
sl@0
    53
				 * (native). */
sl@0
    54
{
sl@0
    55
    CONST char *name, *p;
sl@0
    56
    Tcl_StatBuf statBuf;
sl@0
    57
    int length;
sl@0
    58
    Tcl_DString buffer, nameString;
sl@0
    59
#ifdef __SYMBIAN32__     
sl@0
    60
    char bufferUsed;
sl@0
    61
#endif
sl@0
    62
sl@0
    63
    if (argv0 == NULL) {
sl@0
    64
	return NULL;
sl@0
    65
    }
sl@0
    66
    if (tclNativeExecutableName != NULL) {
sl@0
    67
	return tclNativeExecutableName;
sl@0
    68
    }
sl@0
    69
sl@0
    70
#ifdef __SYMBIAN32__     
sl@0
    71
    // assuming if we're not using eshell that we have to specify the path.
sl@0
    72
    bufferUsed = 0;
sl@0
    73
    if (!strstr(argv0, "Z:\\sys\\bin")) {
sl@0
    74
    	Tcl_DStringInit(&buffer);
sl@0
    75
    	Tcl_DStringSetLength(&buffer, 0);
sl@0
    76
    	Tcl_DStringAppend(&buffer, "Z:\\sys\\bin\\", 11);
sl@0
    77
    	name = Tcl_DStringAppend(&buffer, argv0, -1);
sl@0
    78
        bufferUsed = 1;
sl@0
    79
    }
sl@0
    80
    else    
sl@0
    81
    	name = argv0;  //use if we don't have to specify the path.
sl@0
    82
    
sl@0
    83
    tclNativeExecutableName = ckalloc((unsigned) (strlen(name) + 1));
sl@0
    84
    strcpy(tclNativeExecutableName, name);
sl@0
    85
sl@0
    86
    tclCopySymbianPathSlashConversion(TO_TCL, tclNativeExecutableName, tclNativeExecutableName);  
sl@0
    87
 
sl@0
    88
    if (bufferUsed) {
sl@0
    89
    	Tcl_DStringFree(&buffer);
sl@0
    90
    }
sl@0
    91
    
sl@0
    92
    return tclNativeExecutableName;    
sl@0
    93
#else    
sl@0
    94
    
sl@0
    95
sl@0
    96
    Tcl_DStringInit(&buffer);
sl@0
    97
sl@0
    98
    name = argv0;
sl@0
    99
    for (p = name; *p != '\0'; p++) {
sl@0
   100
	if (*p == '/') {
sl@0
   101
	    /*
sl@0
   102
	     * The name contains a slash, so use the name directly
sl@0
   103
	     * without doing a path search.
sl@0
   104
	     */
sl@0
   105
sl@0
   106
	    goto gotName;
sl@0
   107
	}
sl@0
   108
    }
sl@0
   109
sl@0
   110
    p = getenv("PATH");					/* INTL: Native. */
sl@0
   111
    if (p == NULL) {
sl@0
   112
	/*
sl@0
   113
	 * There's no PATH environment variable; use the default that
sl@0
   114
	 * is used by sh.
sl@0
   115
	 */
sl@0
   116
sl@0
   117
	p = ":/bin:/usr/bin";
sl@0
   118
    } else if (*p == '\0') {
sl@0
   119
	/*
sl@0
   120
	 * An empty path is equivalent to ".".
sl@0
   121
	 */
sl@0
   122
sl@0
   123
	p = "./";
sl@0
   124
    }
sl@0
   125
sl@0
   126
    /*
sl@0
   127
     * Search through all the directories named in the PATH variable
sl@0
   128
     * to see if argv[0] is in one of them.  If so, use that file
sl@0
   129
     * name.
sl@0
   130
     */
sl@0
   131
sl@0
   132
    while (1) {
sl@0
   133
	while (isspace(UCHAR(*p))) {		/* INTL: BUG */
sl@0
   134
	    p++;
sl@0
   135
	}
sl@0
   136
	name = p;
sl@0
   137
	while ((*p != ':') && (*p != 0)) {
sl@0
   138
	    p++;
sl@0
   139
	}
sl@0
   140
	Tcl_DStringSetLength(&buffer, 0);
sl@0
   141
	if (p != name) {
sl@0
   142
	    Tcl_DStringAppend(&buffer, name, p - name);
sl@0
   143
	    if (p[-1] != '/') {
sl@0
   144
		Tcl_DStringAppend(&buffer, "/", 1);
sl@0
   145
	    }
sl@0
   146
	}
sl@0
   147
	name = Tcl_DStringAppend(&buffer, argv0, -1);
sl@0
   148
sl@0
   149
	/*
sl@0
   150
	 * INTL: The following calls to access() and stat() should not be
sl@0
   151
	 * converted to Tclp routines because they need to operate on native
sl@0
   152
	 * strings directly.
sl@0
   153
	 */
sl@0
   154
sl@0
   155
	if ((access(name, X_OK) == 0)			/* INTL: Native. */
sl@0
   156
		&& (TclOSstat(name, &statBuf) == 0)	/* INTL: Native. */
sl@0
   157
		&& S_ISREG(statBuf.st_mode)) {
sl@0
   158
	    goto gotName;
sl@0
   159
	}
sl@0
   160
	if (*p == '\0') {
sl@0
   161
	    break;
sl@0
   162
	} else if (*(p+1) == 0) {
sl@0
   163
	    p = "./";
sl@0
   164
	} else {
sl@0
   165
	    p++;
sl@0
   166
	}
sl@0
   167
    }
sl@0
   168
    goto done;
sl@0
   169
sl@0
   170
    /*
sl@0
   171
     * If the name starts with "/" then just copy it to tclExecutableName.
sl@0
   172
     */
sl@0
   173
sl@0
   174
gotName:
sl@0
   175
#ifdef DJGPP
sl@0
   176
    if (name[1] == ':')  {
sl@0
   177
#else
sl@0
   178
    if (name[0] == '/')  {
sl@0
   179
#endif
sl@0
   180
	Tcl_ExternalToUtfDString(NULL, name, -1, &nameString);
sl@0
   181
	tclNativeExecutableName = (char *)
sl@0
   182
		ckalloc((unsigned) (Tcl_DStringLength(&nameString) + 1));
sl@0
   183
	strcpy(tclNativeExecutableName, Tcl_DStringValue(&nameString));
sl@0
   184
	Tcl_DStringFree(&nameString);
sl@0
   185
	goto done;
sl@0
   186
    }
sl@0
   187
sl@0
   188
    /*
sl@0
   189
     * The name is relative to the current working directory.  First
sl@0
   190
     * strip off a leading "./", if any, then add the full path name of
sl@0
   191
     * the current working directory.
sl@0
   192
     */
sl@0
   193
sl@0
   194
    if ((name[0] == '.') && (name[1] == '/')) {
sl@0
   195
	name += 2;
sl@0
   196
    }
sl@0
   197
sl@0
   198
    Tcl_ExternalToUtfDString(NULL, name, -1, &nameString);
sl@0
   199
sl@0
   200
    Tcl_DStringFree(&buffer);
sl@0
   201
    TclpGetCwd(NULL, &buffer);
sl@0
   202
sl@0
   203
    length = Tcl_DStringLength(&buffer) + Tcl_DStringLength(&nameString) + 2;
sl@0
   204
    tclNativeExecutableName = (char *) ckalloc((unsigned) length);
sl@0
   205
    strcpy(tclNativeExecutableName, Tcl_DStringValue(&buffer));
sl@0
   206
    tclNativeExecutableName[Tcl_DStringLength(&buffer)] = '/';
sl@0
   207
    strcpy(tclNativeExecutableName + Tcl_DStringLength(&buffer) + 1,
sl@0
   208
	    Tcl_DStringValue(&nameString));
sl@0
   209
    Tcl_DStringFree(&nameString);
sl@0
   210
sl@0
   211
#endif    
sl@0
   212
    
sl@0
   213
done:
sl@0
   214
    Tcl_DStringFree(&buffer);
sl@0
   215
    return tclNativeExecutableName;
sl@0
   216
}
sl@0
   217

sl@0
   218
/*
sl@0
   219
 *----------------------------------------------------------------------
sl@0
   220
 *
sl@0
   221
 * TclpMatchInDirectory --
sl@0
   222
 *
sl@0
   223
 *	This routine is used by the globbing code to search a
sl@0
   224
 *	directory for all files which match a given pattern.
sl@0
   225
 *
sl@0
   226
 * Results: 
sl@0
   227
 *	The return value is a standard Tcl result indicating whether an
sl@0
   228
 *	error occurred in globbing.  Errors are left in interp, good
sl@0
   229
 *	results are lappended to resultPtr (which must be a valid object)
sl@0
   230
 *
sl@0
   231
 * Side effects:
sl@0
   232
 *	None.
sl@0
   233
 *
sl@0
   234
 *---------------------------------------------------------------------- */
sl@0
   235
sl@0
   236
int
sl@0
   237
TclpMatchInDirectory(interp, resultPtr, pathPtr, pattern, types)
sl@0
   238
    Tcl_Interp *interp;		/* Interpreter to receive errors. */
sl@0
   239
    Tcl_Obj *resultPtr;		/* List object to lappend results. */
sl@0
   240
    Tcl_Obj *pathPtr;	        /* Contains path to directory to search. */
sl@0
   241
    CONST char *pattern;	/* Pattern to match against. */
sl@0
   242
    Tcl_GlobTypeData *types;	/* Object containing list of acceptable types.
sl@0
   243
				 * May be NULL. In particular the directory
sl@0
   244
				 * flag is very important. */
sl@0
   245
{
sl@0
   246
    CONST char *native;
sl@0
   247
    Tcl_Obj *fileNamePtr;
sl@0
   248
sl@0
   249
    fileNamePtr = Tcl_FSGetTranslatedPath(interp, pathPtr);
sl@0
   250
    if (fileNamePtr == NULL) {
sl@0
   251
	return TCL_ERROR;
sl@0
   252
    }
sl@0
   253
    
sl@0
   254
    if (pattern == NULL || (*pattern == '\0')) {
sl@0
   255
	/* Match a file directly */
sl@0
   256
	native = (CONST char*) Tcl_FSGetNativePath(pathPtr);
sl@0
   257
	if (NativeMatchType(native, types)) {
sl@0
   258
	    Tcl_ListObjAppendElement(interp, resultPtr, pathPtr);
sl@0
   259
	}
sl@0
   260
	Tcl_DecrRefCount(fileNamePtr);
sl@0
   261
	return TCL_OK;
sl@0
   262
    } else {
sl@0
   263
	DIR *d;
sl@0
   264
	Tcl_DirEntry *entryPtr;
sl@0
   265
	CONST char *dirName;
sl@0
   266
	int dirLength;
sl@0
   267
	int matchHidden;
sl@0
   268
	int nativeDirLen;
sl@0
   269
	Tcl_StatBuf statBuf;
sl@0
   270
	Tcl_DString ds;      /* native encoding of dir */
sl@0
   271
	Tcl_DString dsOrig;  /* utf-8 encoding of dir */
sl@0
   272
sl@0
   273
	Tcl_DStringInit(&dsOrig);
sl@0
   274
	dirName = Tcl_GetStringFromObj(fileNamePtr, &dirLength);
sl@0
   275
	Tcl_DStringAppend(&dsOrig, dirName, dirLength);
sl@0
   276
	
sl@0
   277
	/*
sl@0
   278
	 * Make sure that the directory part of the name really is a
sl@0
   279
	 * directory.  If the directory name is "", use the name "."
sl@0
   280
	 * instead, because some UNIX systems don't treat "" like "."
sl@0
   281
	 * automatically.  Keep the "" for use in generating file names,
sl@0
   282
	 * otherwise "glob foo.c" would return "./foo.c".
sl@0
   283
	 */
sl@0
   284
sl@0
   285
	if (dirLength == 0) {
sl@0
   286
	    dirName = ".";
sl@0
   287
	} else {
sl@0
   288
	    dirName = Tcl_DStringValue(&dsOrig);
sl@0
   289
	    /* Make sure we have a trailing directory delimiter */
sl@0
   290
	    if (dirName[dirLength-1] != '/') {
sl@0
   291
		dirName = Tcl_DStringAppend(&dsOrig, "/", 1);
sl@0
   292
		dirLength++;
sl@0
   293
	    }
sl@0
   294
	}
sl@0
   295
	Tcl_DecrRefCount(fileNamePtr);
sl@0
   296
	
sl@0
   297
	/*
sl@0
   298
	 * Now open the directory for reading and iterate over the contents.
sl@0
   299
	 */
sl@0
   300
sl@0
   301
	native = Tcl_UtfToExternalDString(NULL, dirName, -1, &ds);
sl@0
   302
sl@0
   303
	if ((TclOSstat(native, &statBuf) != 0)		/* INTL: Native. */
sl@0
   304
		|| !S_ISDIR(statBuf.st_mode)) {
sl@0
   305
	    Tcl_DStringFree(&dsOrig);
sl@0
   306
	    Tcl_DStringFree(&ds);
sl@0
   307
	    return TCL_OK;
sl@0
   308
	}
sl@0
   309
sl@0
   310
	d = opendir(native);				/* INTL: Native. */
sl@0
   311
	if (d == NULL) {
sl@0
   312
	    Tcl_DStringFree(&ds);
sl@0
   313
	    Tcl_ResetResult(interp);
sl@0
   314
	    Tcl_AppendResult(interp, "couldn't read directory \"",
sl@0
   315
		    Tcl_DStringValue(&dsOrig), "\": ",
sl@0
   316
		    Tcl_PosixError(interp), (char *) NULL);
sl@0
   317
	    Tcl_DStringFree(&dsOrig);
sl@0
   318
	    return TCL_ERROR;
sl@0
   319
	}
sl@0
   320
sl@0
   321
	nativeDirLen = Tcl_DStringLength(&ds);
sl@0
   322
sl@0
   323
	/*
sl@0
   324
	 * Check to see if -type or the pattern requests hidden files.
sl@0
   325
	 */
sl@0
   326
	matchHidden = ((types && (types->perm & TCL_GLOB_PERM_HIDDEN)) ||
sl@0
   327
		((pattern[0] == '.')
sl@0
   328
			|| ((pattern[0] == '\\') && (pattern[1] == '.'))));
sl@0
   329
sl@0
   330
	while ((entryPtr = TclOSreaddir(d)) != NULL) { /* INTL: Native. */
sl@0
   331
	    Tcl_DString utfDs;
sl@0
   332
	    CONST char *utfname;
sl@0
   333
sl@0
   334
	    /* 
sl@0
   335
	     * Skip this file if it doesn't agree with the hidden
sl@0
   336
	     * parameters requested by the user (via -type or pattern).
sl@0
   337
	     */
sl@0
   338
	    if (*entryPtr->d_name == '.') {
sl@0
   339
		if (!matchHidden) continue;
sl@0
   340
	    } else {
sl@0
   341
		if (matchHidden) continue;
sl@0
   342
	    }
sl@0
   343
sl@0
   344
	    /*
sl@0
   345
	     * Now check to see if the file matches, according to both type
sl@0
   346
	     * and pattern.  If so, add the file to the result.
sl@0
   347
	     */
sl@0
   348
sl@0
   349
	    utfname = Tcl_ExternalToUtfDString(NULL, entryPtr->d_name,
sl@0
   350
		    -1, &utfDs);
sl@0
   351
	    if (Tcl_StringCaseMatch(utfname, pattern, 0)) {
sl@0
   352
		int typeOk = 1;
sl@0
   353
sl@0
   354
		if (types != NULL) {
sl@0
   355
		    Tcl_DStringSetLength(&ds, nativeDirLen);
sl@0
   356
		    native = Tcl_DStringAppend(&ds, entryPtr->d_name, -1);
sl@0
   357
		    typeOk = NativeMatchType(native, types);
sl@0
   358
		}
sl@0
   359
		if (typeOk) {
sl@0
   360
		    Tcl_ListObjAppendElement(interp, resultPtr, 
sl@0
   361
			    TclNewFSPathObj(pathPtr, utfname,
sl@0
   362
				    Tcl_DStringLength(&utfDs)));
sl@0
   363
		}
sl@0
   364
	    }
sl@0
   365
	    Tcl_DStringFree(&utfDs);
sl@0
   366
	}
sl@0
   367
sl@0
   368
	closedir(d);
sl@0
   369
	Tcl_DStringFree(&ds);
sl@0
   370
	Tcl_DStringFree(&dsOrig);
sl@0
   371
	return TCL_OK;
sl@0
   372
    }
sl@0
   373
}
sl@0
   374
static int 
sl@0
   375
NativeMatchType(
sl@0
   376
    CONST char* nativeEntry,  /* Native path to check */
sl@0
   377
    Tcl_GlobTypeData *types)  /* Type description to match against */
sl@0
   378
{
sl@0
   379
    Tcl_StatBuf buf;
sl@0
   380
    if (types == NULL) {
sl@0
   381
	/* 
sl@0
   382
	 * Simply check for the file's existence, but do it
sl@0
   383
	 * with lstat, in case it is a link to a file which
sl@0
   384
	 * doesn't exist (since that case would not show up
sl@0
   385
	 * if we used 'access' or 'stat')
sl@0
   386
	 */
sl@0
   387
	if (TclOSlstat(nativeEntry, &buf) != 0) {
sl@0
   388
	    return 0;
sl@0
   389
	}
sl@0
   390
    } else {
sl@0
   391
	if (types->perm != 0) {
sl@0
   392
	    if (TclOSstat(nativeEntry, &buf) != 0) {
sl@0
   393
		/* 
sl@0
   394
		 * Either the file has disappeared between the
sl@0
   395
		 * 'readdir' call and the 'stat' call, or
sl@0
   396
		 * the file is a link to a file which doesn't
sl@0
   397
		 * exist (which we could ascertain with
sl@0
   398
		 * lstat), or there is some other strange
sl@0
   399
		 * problem.  In all these cases, we define this
sl@0
   400
		 * to mean the file does not match any defined
sl@0
   401
		 * permission, and therefore it is not 
sl@0
   402
		 * added to the list of files to return.
sl@0
   403
		 */
sl@0
   404
		return 0;
sl@0
   405
	    }
sl@0
   406
	    
sl@0
   407
	    /* 
sl@0
   408
	     * readonly means that there are NO write permissions
sl@0
   409
	     * (even for user), but execute is OK for anybody
sl@0
   410
	     */
sl@0
   411
	    if (((types->perm & TCL_GLOB_PERM_RONLY) &&
sl@0
   412
			(buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
sl@0
   413
		((types->perm & TCL_GLOB_PERM_R) &&
sl@0
   414
			(access(nativeEntry, R_OK) != 0)) ||
sl@0
   415
		((types->perm & TCL_GLOB_PERM_W) &&
sl@0
   416
			(access(nativeEntry, W_OK) != 0)) ||
sl@0
   417
		((types->perm & TCL_GLOB_PERM_X) &&
sl@0
   418
			(access(nativeEntry, X_OK) != 0))
sl@0
   419
		) {
sl@0
   420
		return 0;
sl@0
   421
	    }
sl@0
   422
	}
sl@0
   423
	if (types->type != 0) {
sl@0
   424
	    if (types->perm == 0) {
sl@0
   425
		/* We haven't yet done a stat on the file */
sl@0
   426
		if (TclOSstat(nativeEntry, &buf) != 0) {
sl@0
   427
		    /* 
sl@0
   428
		     * Posix error occurred.  The only ok
sl@0
   429
		     * case is if this is a link to a nonexistent
sl@0
   430
		     * file, and the user did 'glob -l'. So
sl@0
   431
		     * we check that here:
sl@0
   432
		     */
sl@0
   433
		    if (types->type & TCL_GLOB_TYPE_LINK) {
sl@0
   434
			if (TclOSlstat(nativeEntry, &buf) == 0) {
sl@0
   435
			    if (S_ISLNK(buf.st_mode)) {
sl@0
   436
				return 1;
sl@0
   437
			    }
sl@0
   438
			}
sl@0
   439
		    }
sl@0
   440
		    return 0;
sl@0
   441
		}
sl@0
   442
	    }
sl@0
   443
	    /*
sl@0
   444
	     * In order bcdpfls as in 'find -t'
sl@0
   445
	     */
sl@0
   446
	    if (
sl@0
   447
		((types->type & TCL_GLOB_TYPE_BLOCK) &&
sl@0
   448
			S_ISBLK(buf.st_mode)) ||
sl@0
   449
		((types->type & TCL_GLOB_TYPE_CHAR) &&
sl@0
   450
			S_ISCHR(buf.st_mode)) ||
sl@0
   451
		((types->type & TCL_GLOB_TYPE_DIR) &&
sl@0
   452
			S_ISDIR(buf.st_mode)) ||
sl@0
   453
		((types->type & TCL_GLOB_TYPE_PIPE) &&
sl@0
   454
			S_ISFIFO(buf.st_mode)) ||
sl@0
   455
		((types->type & TCL_GLOB_TYPE_FILE) &&
sl@0
   456
			S_ISREG(buf.st_mode))
sl@0
   457
#ifdef S_ISSOCK
sl@0
   458
		|| ((types->type & TCL_GLOB_TYPE_SOCK) &&
sl@0
   459
			S_ISSOCK(buf.st_mode))
sl@0
   460
#endif /* S_ISSOCK */
sl@0
   461
		) {
sl@0
   462
		/* Do nothing -- this file is ok */
sl@0
   463
	    } else {
sl@0
   464
#ifdef S_ISLNK
sl@0
   465
		if (types->type & TCL_GLOB_TYPE_LINK) {
sl@0
   466
		    if (TclOSlstat(nativeEntry, &buf) == 0) {
sl@0
   467
			if (S_ISLNK(buf.st_mode)) {
sl@0
   468
			    return 1;
sl@0
   469
			}
sl@0
   470
		    }
sl@0
   471
		}
sl@0
   472
#endif /* S_ISLNK */
sl@0
   473
		return 0;
sl@0
   474
	    }
sl@0
   475
	}
sl@0
   476
    }
sl@0
   477
    return 1;
sl@0
   478
}
sl@0
   479

sl@0
   480
/*
sl@0
   481
 *---------------------------------------------------------------------------
sl@0
   482
 *
sl@0
   483
 * TclpGetUserHome --
sl@0
   484
 *
sl@0
   485
 *	This function takes the specified user name and finds their
sl@0
   486
 *	home directory.
sl@0
   487
 *
sl@0
   488
 * Results:
sl@0
   489
 *	The result is a pointer to a string specifying the user's home
sl@0
   490
 *	directory, or NULL if the user's home directory could not be
sl@0
   491
 *	determined.  Storage for the result string is allocated in
sl@0
   492
 *	bufferPtr; the caller must call Tcl_DStringFree() when the result
sl@0
   493
 *	is no longer needed.
sl@0
   494
 *
sl@0
   495
 * Side effects:
sl@0
   496
 *	None.
sl@0
   497
 *
sl@0
   498
 *----------------------------------------------------------------------
sl@0
   499
 */
sl@0
   500
sl@0
   501
char *
sl@0
   502
TclpGetUserHome(name, bufferPtr)
sl@0
   503
    CONST char *name;		/* User name for desired home directory. */
sl@0
   504
    Tcl_DString *bufferPtr;	/* Uninitialized or free DString filled
sl@0
   505
				 * with name of user's home directory. */
sl@0
   506
{
sl@0
   507
    struct passwd *pwPtr;
sl@0
   508
    Tcl_DString ds;
sl@0
   509
    CONST char *native;
sl@0
   510
sl@0
   511
    native = Tcl_UtfToExternalDString(NULL, name, -1, &ds);
sl@0
   512
    pwPtr = getpwnam(native);				/* INTL: Native. */
sl@0
   513
    Tcl_DStringFree(&ds);
sl@0
   514
    
sl@0
   515
    if (pwPtr == NULL) {
sl@0
   516
	endpwent();
sl@0
   517
	return NULL;
sl@0
   518
    }
sl@0
   519
    Tcl_ExternalToUtfDString(NULL, pwPtr->pw_dir, -1, bufferPtr);
sl@0
   520
    endpwent();
sl@0
   521
    return Tcl_DStringValue(bufferPtr);
sl@0
   522
}
sl@0
   523

sl@0
   524
/*
sl@0
   525
 *---------------------------------------------------------------------------
sl@0
   526
 *
sl@0
   527
 * TclpObjAccess --
sl@0
   528
 *
sl@0
   529
 *	This function replaces the library version of access().
sl@0
   530
 *
sl@0
   531
 * Results:
sl@0
   532
 *	See access() documentation.
sl@0
   533
 *
sl@0
   534
 * Side effects:
sl@0
   535
 *	See access() documentation.
sl@0
   536
 *
sl@0
   537
 *---------------------------------------------------------------------------
sl@0
   538
 */
sl@0
   539
sl@0
   540
int 
sl@0
   541
TclpObjAccess(pathPtr, mode)
sl@0
   542
    Tcl_Obj *pathPtr;        /* Path of file to access */
sl@0
   543
    int mode;                /* Permission setting. */
sl@0
   544
{
sl@0
   545
    CONST char *path = Tcl_FSGetNativePath(pathPtr);
sl@0
   546
    if (path == NULL) {
sl@0
   547
	return -1;
sl@0
   548
    } else {
sl@0
   549
	return access(path, mode);
sl@0
   550
    }
sl@0
   551
}
sl@0
   552

sl@0
   553
/*
sl@0
   554
 *---------------------------------------------------------------------------
sl@0
   555
 *
sl@0
   556
 * TclpObjChdir --
sl@0
   557
 *
sl@0
   558
 *	This function replaces the library version of chdir().
sl@0
   559
 *
sl@0
   560
 * Results:
sl@0
   561
 *	See chdir() documentation.
sl@0
   562
 *
sl@0
   563
 * Side effects:
sl@0
   564
 *	See chdir() documentation.  
sl@0
   565
 *
sl@0
   566
 *---------------------------------------------------------------------------
sl@0
   567
 */
sl@0
   568
sl@0
   569
int 
sl@0
   570
TclpObjChdir(pathPtr)
sl@0
   571
    Tcl_Obj *pathPtr;          /* Path to new working directory */
sl@0
   572
{
sl@0
   573
    CONST char *path = Tcl_FSGetNativePath(pathPtr);
sl@0
   574
    if (path == NULL) {
sl@0
   575
	return -1;
sl@0
   576
    } else {
sl@0
   577
	return chdir(path);
sl@0
   578
    }
sl@0
   579
}
sl@0
   580

sl@0
   581
/*
sl@0
   582
 *----------------------------------------------------------------------
sl@0
   583
 *
sl@0
   584
 * TclpObjLstat --
sl@0
   585
 *
sl@0
   586
 *	This function replaces the library version of lstat().
sl@0
   587
 *
sl@0
   588
 * Results:
sl@0
   589
 *	See lstat() documentation.
sl@0
   590
 *
sl@0
   591
 * Side effects:
sl@0
   592
 *	See lstat() documentation.
sl@0
   593
 *
sl@0
   594
 *----------------------------------------------------------------------
sl@0
   595
 */
sl@0
   596
sl@0
   597
int 
sl@0
   598
TclpObjLstat(pathPtr, bufPtr)
sl@0
   599
    Tcl_Obj *pathPtr;		/* Path of file to stat */
sl@0
   600
    Tcl_StatBuf *bufPtr;	/* Filled with results of stat call. */
sl@0
   601
{
sl@0
   602
    return TclOSlstat(Tcl_FSGetNativePath(pathPtr), bufPtr);
sl@0
   603
}
sl@0
   604

sl@0
   605
/*
sl@0
   606
 *---------------------------------------------------------------------------
sl@0
   607
 *
sl@0
   608
 * TclpObjGetCwd --
sl@0
   609
 *
sl@0
   610
 *	This function replaces the library version of getcwd().
sl@0
   611
 *
sl@0
   612
 * Results:
sl@0
   613
 *	The result is a pointer to a string specifying the current
sl@0
   614
 *	directory, or NULL if the current directory could not be
sl@0
   615
 *	determined.  If NULL is returned, an error message is left in the
sl@0
   616
 *	interp's result.  Storage for the result string is allocated in
sl@0
   617
 *	bufferPtr; the caller must call Tcl_DStringFree() when the result
sl@0
   618
 *	is no longer needed.
sl@0
   619
 *
sl@0
   620
 * Side effects:
sl@0
   621
 *	None.
sl@0
   622
 *
sl@0
   623
 *----------------------------------------------------------------------
sl@0
   624
 */
sl@0
   625
sl@0
   626
Tcl_Obj* 
sl@0
   627
TclpObjGetCwd(interp)
sl@0
   628
    Tcl_Interp *interp;
sl@0
   629
{
sl@0
   630
    Tcl_DString ds;
sl@0
   631
    if (TclpGetCwd(interp, &ds) != NULL) {
sl@0
   632
	Tcl_Obj *cwdPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), -1);
sl@0
   633
	Tcl_IncrRefCount(cwdPtr);
sl@0
   634
	Tcl_DStringFree(&ds);
sl@0
   635
	return cwdPtr;
sl@0
   636
    } else {
sl@0
   637
	return NULL;
sl@0
   638
    }
sl@0
   639
}
sl@0
   640
sl@0
   641
/* Older string based version */
sl@0
   642
CONST char *
sl@0
   643
TclpGetCwd(interp, bufferPtr)
sl@0
   644
    Tcl_Interp *interp;		/* If non-NULL, used for error reporting. */
sl@0
   645
    Tcl_DString *bufferPtr;	/* Uninitialized or free DString filled
sl@0
   646
				 * with name of current directory. */
sl@0
   647
{
sl@0
   648
    char buffer[MAXPATHLEN+1];
sl@0
   649
sl@0
   650
#ifdef USEGETWD
sl@0
   651
    if (getwd(buffer) == NULL) {			/* INTL: Native. */
sl@0
   652
#else
sl@0
   653
    if (getcwd(buffer, MAXPATHLEN + 1) == NULL) {	/* INTL: Native. */
sl@0
   654
#endif
sl@0
   655
	if (interp != NULL) {
sl@0
   656
	    Tcl_AppendResult(interp,
sl@0
   657
		    "error getting working directory name: ",
sl@0
   658
		    Tcl_PosixError(interp), (char *) NULL);
sl@0
   659
	}
sl@0
   660
	return NULL;
sl@0
   661
    }
sl@0
   662
	/* TODO - the line bellow is a temporary patch. The defect number is: DEF116621. */
sl@0
   663
	buffer[0] = 'c';
sl@0
   664
    return Tcl_ExternalToUtfDString(NULL, buffer, -1, bufferPtr);
sl@0
   665
}
sl@0
   666

sl@0
   667
/*
sl@0
   668
 *---------------------------------------------------------------------------
sl@0
   669
 *
sl@0
   670
 * TclpReadlink --
sl@0
   671
 *
sl@0
   672
 *	This function replaces the library version of readlink().
sl@0
   673
 *
sl@0
   674
 * Results:
sl@0
   675
 *	The result is a pointer to a string specifying the contents
sl@0
   676
 *	of the symbolic link given by 'path', or NULL if the symbolic
sl@0
   677
 *	link could not be read.  Storage for the result string is
sl@0
   678
 *	allocated in bufferPtr; the caller must call Tcl_DStringFree()
sl@0
   679
 *	when the result is no longer needed.
sl@0
   680
 *
sl@0
   681
 * Side effects:
sl@0
   682
 *	See readlink() documentation.
sl@0
   683
 *
sl@0
   684
 *---------------------------------------------------------------------------
sl@0
   685
 */
sl@0
   686
sl@0
   687
char *
sl@0
   688
TclpReadlink(path, linkPtr)
sl@0
   689
    CONST char *path;		/* Path of file to readlink (UTF-8). */
sl@0
   690
    Tcl_DString *linkPtr;	/* Uninitialized or free DString filled
sl@0
   691
				 * with contents of link (UTF-8). */
sl@0
   692
{
sl@0
   693
#ifndef DJGPP
sl@0
   694
    char link[MAXPATHLEN];
sl@0
   695
    int length;
sl@0
   696
    CONST char *native;
sl@0
   697
    Tcl_DString ds;
sl@0
   698
sl@0
   699
    native = Tcl_UtfToExternalDString(NULL, path, -1, &ds);
sl@0
   700
    length = readlink(native, link, sizeof(link));	/* INTL: Native. */
sl@0
   701
    Tcl_DStringFree(&ds);
sl@0
   702
    
sl@0
   703
    if (length < 0) {
sl@0
   704
	return NULL;
sl@0
   705
    }
sl@0
   706
sl@0
   707
    Tcl_ExternalToUtfDString(NULL, link, length, linkPtr);
sl@0
   708
    return Tcl_DStringValue(linkPtr);
sl@0
   709
#else
sl@0
   710
    return NULL;
sl@0
   711
#endif
sl@0
   712
}
sl@0
   713

sl@0
   714
/*
sl@0
   715
 *----------------------------------------------------------------------
sl@0
   716
 *
sl@0
   717
 * TclpObjStat --
sl@0
   718
 *
sl@0
   719
 *	This function replaces the library version of stat().
sl@0
   720
 *
sl@0
   721
 * Results:
sl@0
   722
 *	See stat() documentation.
sl@0
   723
 *
sl@0
   724
 * Side effects:
sl@0
   725
 *	See stat() documentation.
sl@0
   726
 *
sl@0
   727
 *----------------------------------------------------------------------
sl@0
   728
 */
sl@0
   729
sl@0
   730
int 
sl@0
   731
TclpObjStat(pathPtr, bufPtr)
sl@0
   732
    Tcl_Obj *pathPtr;		/* Path of file to stat */
sl@0
   733
    Tcl_StatBuf *bufPtr;	/* Filled with results of stat call. */
sl@0
   734
{
sl@0
   735
    CONST char *path = Tcl_FSGetNativePath(pathPtr);
sl@0
   736
    if (path == NULL) {
sl@0
   737
	return -1;
sl@0
   738
    } else {
sl@0
   739
	return TclOSstat(path, bufPtr);
sl@0
   740
    }
sl@0
   741
}
sl@0
   742

sl@0
   743
sl@0
   744
#ifdef S_IFLNK
sl@0
   745
sl@0
   746
Tcl_Obj* 
sl@0
   747
TclpObjLink(pathPtr, toPtr, linkAction)
sl@0
   748
    Tcl_Obj *pathPtr;
sl@0
   749
    Tcl_Obj *toPtr;
sl@0
   750
    int linkAction;
sl@0
   751
{
sl@0
   752
    if (toPtr != NULL) {
sl@0
   753
	CONST char *src = Tcl_FSGetNativePath(pathPtr);
sl@0
   754
	CONST char *target = Tcl_FSGetNativePath(toPtr);
sl@0
   755
	
sl@0
   756
	if (src == NULL || target == NULL) {
sl@0
   757
	    return NULL;
sl@0
   758
	}
sl@0
   759
	if (access(src, F_OK) != -1) {
sl@0
   760
	    /* src exists */
sl@0
   761
	    errno = EEXIST;
sl@0
   762
	    return NULL;
sl@0
   763
	}
sl@0
   764
	if (access(target, F_OK) == -1) {
sl@0
   765
	    /* target doesn't exist */
sl@0
   766
	    errno = ENOENT;
sl@0
   767
	    return NULL;
sl@0
   768
	}
sl@0
   769
	/* 
sl@0
   770
	 * Check symbolic link flag first, since we prefer to
sl@0
   771
	 * create these.
sl@0
   772
	 */
sl@0
   773
	if (linkAction & TCL_CREATE_SYMBOLIC_LINK) {
sl@0
   774
	    if (symlink(target, src) != 0) return NULL;
sl@0
   775
	} else if (linkAction & TCL_CREATE_HARD_LINK) {
sl@0
   776
	    if (link(target, src) != 0) return NULL;
sl@0
   777
	} else {
sl@0
   778
	    errno = ENODEV;
sl@0
   779
	    return NULL;
sl@0
   780
	}
sl@0
   781
	return toPtr;
sl@0
   782
    } else {
sl@0
   783
	Tcl_Obj* linkPtr = NULL;
sl@0
   784
sl@0
   785
	char link[MAXPATHLEN];
sl@0
   786
	int length;
sl@0
   787
	Tcl_DString ds;
sl@0
   788
	Tcl_Obj *transPtr;
sl@0
   789
	
sl@0
   790
	transPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr);
sl@0
   791
	if (transPtr == NULL) {
sl@0
   792
	    return NULL;
sl@0
   793
	}
sl@0
   794
	Tcl_DecrRefCount(transPtr);
sl@0
   795
	
sl@0
   796
	length = readlink(Tcl_FSGetNativePath(pathPtr), link, sizeof(link));
sl@0
   797
	if (length < 0) {
sl@0
   798
	    return NULL;
sl@0
   799
	}
sl@0
   800
sl@0
   801
	Tcl_ExternalToUtfDString(NULL, link, length, &ds);
sl@0
   802
	linkPtr = Tcl_NewStringObj(Tcl_DStringValue(&ds), 
sl@0
   803
				   Tcl_DStringLength(&ds));
sl@0
   804
	Tcl_DStringFree(&ds);
sl@0
   805
	if (linkPtr != NULL) {
sl@0
   806
	    Tcl_IncrRefCount(linkPtr);
sl@0
   807
	}
sl@0
   808
	return linkPtr;
sl@0
   809
    }
sl@0
   810
}
sl@0
   811
sl@0
   812
#endif
sl@0
   813
sl@0
   814

sl@0
   815
/*
sl@0
   816
 *---------------------------------------------------------------------------
sl@0
   817
 *
sl@0
   818
 * TclpFilesystemPathType --
sl@0
   819
 *
sl@0
   820
 *      This function is part of the native filesystem support, and
sl@0
   821
 *      returns the path type of the given path.  Right now it simply
sl@0
   822
 *      returns NULL.  In the future it could return specific path
sl@0
   823
 *      types, like 'nfs', 'samba', 'FAT32', etc.
sl@0
   824
 *
sl@0
   825
 * Results:
sl@0
   826
 *      NULL at present.
sl@0
   827
 *
sl@0
   828
 * Side effects:
sl@0
   829
 *	None.
sl@0
   830
 *
sl@0
   831
 *---------------------------------------------------------------------------
sl@0
   832
 */
sl@0
   833
Tcl_Obj*
sl@0
   834
TclpFilesystemPathType(pathObjPtr)
sl@0
   835
    Tcl_Obj* pathObjPtr;
sl@0
   836
{
sl@0
   837
    /* All native paths are of the same type */
sl@0
   838
    return NULL;
sl@0
   839
}
sl@0
   840

sl@0
   841
/*
sl@0
   842
 *---------------------------------------------------------------------------
sl@0
   843
 *
sl@0
   844
 * TclpUtime --
sl@0
   845
 *
sl@0
   846
 *	Set the modification date for a file.
sl@0
   847
 *
sl@0
   848
 * Results:
sl@0
   849
 *	0 on success, -1 on error.
sl@0
   850
 *
sl@0
   851
 * Side effects:
sl@0
   852
 *	None.
sl@0
   853
 *
sl@0
   854
 *---------------------------------------------------------------------------
sl@0
   855
 */
sl@0
   856
int 
sl@0
   857
TclpUtime(pathPtr, tval)
sl@0
   858
    Tcl_Obj *pathPtr;      /* File to modify */
sl@0
   859
    struct utimbuf *tval;  /* New modification date structure */
sl@0
   860
{
sl@0
   861
    return utime(Tcl_FSGetNativePath(pathPtr),tval);
sl@0
   862
}