ftp.nice.ch/pub/next/connectivity/infosystems/Archie.2.18.s.tar.gz#/Archie/File.m

This is File.m in view mode; [Download] [Up]

{\rtf0\ansi{\fonttbl\f1\fmodern Courier;\f0\fswiss Helvetica;}
\paperw11440
\paperh9000
\margl120
\margr120
{\colortbl;\red0\green0\blue0;}
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\ulnone\fs24\fc0\cf0 #import <appkit/appkit.h>\
#import "File.h"\
#import "MOString.h"\
#import "ObjectList.h"\
\
#include <ctype.h>\
#include <string.h>\
#include <sys/types.h>\
#include <sys/stat.h>\
#include <sys/param.h>\
#include <sys/dir.h>\
#include <stdio.h>\
#include <string.h>\
#ifndef NIL\
#	define NIL '\\0'\
#endif\
\
@interface File(Private)\
- (
\f0 char *) fileComponent:(char *) path removeLink:(BOOL) flag;\

\f1 @end\
\
@implementation File(Private)\
- (
\f0 char *) fileComponent:(char *) path removeLink:(BOOL) flag\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker483 \markername FileComponent;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul RoutineDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The last component of path if path is\
		not NULL, NULL otherwise;\
	
\i0\ul Description:
\i\ulnone  This routine returns a pointer to the last\
		component in path. Components are assumed to be separated\
		by '/'s.;\
	
\i0\ul Args:
\i\ulnone \
		path: A UNIX style pathname;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 char name[MAXPATHLEN], *arrow, *fileName;\
\
	if( path == 0 )\
		return 0;\
	if( pathString != 0 )\
		free(pathString);\
	strcpy(name, path);\
	
\b0\i /* If the file is a link, truncate the file name prior to the "->" */
\b\i0 \
	arrow = strchr(name, '>');\
	if( arrow != 0 )\
	\{\
		arrow -= 2;\
		*arrow = 0;\
	\}\
	fileName = strrchr(name, '/');\
	if( fileName == 0 )\
		fileName = path;\
	else\
		fileName ++;\
	if( arrow != 0 && flag == NO )\
		*arrow = '>';\
	pathString = NXCopyStringBuffer(fileName);\
\
	return pathString;\
\} 
\b0\i // End fileComponent:
\b\i0 \

\f1 @end\
\
static int DeleteDirectory(char *currentPath)\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker1331 \markername DeleteDirectory;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul RoutineDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  0 if successful, -1 on a system error, and -2\
		if currentPath is not a directory;\
	
\i0\ul Description:
\i\ulnone  This routine d
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 escend
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1 s
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1  through the hierarchy, starting
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1 \
		
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 at currentPath.
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1  
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 Anything other than a directory is removed using
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1 \
		
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 unlink(2).
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1  
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 For a directory, we call ourself recursively.\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1 	
\i0\ul Args:
\i\ulnone \
		currentPath: The pathname to the directory to delete. It must\
			be of sufficient size of hold any pathname, generally this\
			means at least MAXPATHLEN bytes.;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 */
\f0 \

\f1\b\i0\fc0\cf0 struct stat status;\
struct direct *dirp;\
DIR *dp;\
int sys_rtn;\
char *tmpPtr;\
\
	sys_rtn = lstat(currentPath, &status);\

\fc1\cf1 	if ( sys_rtn < 0 )\
		return -1;
\f0\fc0\cf0 	
\b0\i\fc1\cf1 // stat error 
\b\i0\fc0\cf0 \
\
	if ( S_IFDIR & status.st_mode == 0 )\
		return -2;	
\b0\i\fc1\cf1 // Not a directory
\b\i0\fc0\cf0 \
\
	
\b0\i\fc1\cf1 /* It's a directory.  Append a '/' to the directory name for use with\
		the file names returned in the struct direct values from readdir().*/
\b\i0\fc0\cf0 \

\f1 	tmpPtr = index(currentPath, NIL);\
	*tmpPtr++ = '/';\
	*tmpPtr = NIL;\
\

\fc1\cf1 	if( (dp = opendir(currentPath)) == NULL )\
		return -1;
\f0\fc0\cf0 	
\b0\i\fc1\cf1 // Can't read directory
\b\i0\fc0\cf0 \

\f1\fc1\cf1 \
	while ( (dirp = readdir(dp)) != NULL )\
	\{
\f0\fc0\cf0 	
\b0\i\fc1\cf1 /* Process every file but . and .. */
\b\i0\fc0\cf0 \

\f1\fc1\cf1 		if( strcmp(dirp->d_name, ".") == 0  ||\
			strcmp(dirp->d_name, "..") == 0 )\
				continue;\

\f0\fc0\cf0 		
\b0\i\fc1\cf1 /* Build full pathname to file */
\b\i0\fc0\cf0 \

\f1\fc1\cf1 		strcpy(tmpPtr, dirp->d_name);\
		sys_rtn = lstat(currentPath, &status);\
		if ( sys_rtn < 0 )\
			return -1;\
		if( S_IFDIR & status.st_mode )\
			sys_rtn = DeleteDirectory(currentPath);\
		else\
			sys_rtn = unlink(currentPath);\
		if( sys_rtn != 0 )\
			return sys_rtn;\

\f0\fc0\cf0 		
\b0\i\fc1\cf1 /* Reset the path to the current directory */
\b\i0\fc0\cf0 \

\f1\fc1\cf1 		*tmpPtr = NIL;\
	\}\
	tmpPtr[-1] = NIL;\
\

\f0\fc0\cf0 	
\b0\i\fc1\cf1 /* Close and remove this directory */
\b\i0\fc0\cf0 \

\f1\fc1\cf1 	sys_rtn = closedir(dp);\
	sys_rtn = rmdir(currentPath);\
\
	return sys_rtn;\
\}
\f0\fc0\cf0  
\b0\i\fc1\cf1 // End DeleteDirectory()
\b\i0\fc0\cf0 \
\
@implementation File\
NXAtom LocalHost;\
\
+ initialize\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker3112 \markername initialize;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method creates the LocalHost NXAtom;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 */
\f0\b\i0\fc0\cf0 \
	LocalHost = NXUniqueString("LocalHost");\
	/* Turn off umask */\
	umask(0);\
\
	return self;\
\} 
\b0\i // End initialize
\b\i0 \
\

\b0\i\fs28\fc1\cf1 /*\\ --------------------------------- Initialization Methods --------------------------------- \\*/
\b\i0\fs24\fc0\cf0 \
- init:(const char *) filename mode:(const char *) mode size:(int) size\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker3501 \markername init:mode:size:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method is the designated intializer for the\
		File class. It initializes its Date superclass using the\
		
\b initFromNow
\b0  method. The file is assumed\
		to be local and so sets the localPath value to filename and\
		sourceHost to the value LocalHost. A remote file must indicate\
		this through the 
\b setSourceHost:
\b0  method.;\
	
\i0\ul Args:
\i\ulnone \
		filename: The full pathname to the file;\
		mode: The 10 char array with the UNIX style of file permissions;\
		size: The file size in bytes;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 \
	[super initFromNow];\
\
	sourceHost = NULL;\
	localPath = NXCopyStringBuffer(filename);\
	sourcePath = NULL;\
	bcopy(mode, fileMode, 10);\
	fileMode[10] = NIL;\
	fileSize = size;\
	emptyDir = NO;\
	fileInfo = [[FileInfo alloc] init];\
	if( [self isLink] == YES )\
		fileType = eLinkFile;\
	else if( [self isDirectory] == YES )\
		fileType = eDirectoryFile;\
	else\
		fileType = eRegularFile;\
	[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
	if( fileType == eDirectoryFile )\
	\{\
		sortKey = [[DirectorySortKey alloc] init];\
		[sortKey setValue: eSortByName];\
	\}\
\
	return self;\
\} 
\b0\i // End init: mode: size:
\b\i0 \
\
- init:(const char *) filename mode:(const char *) mode size:(int) size\
	day:(int) d month:(int) m year:(int) y hour:(int) hour min:(int) min\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker4810 \markername init:mode:size:day:month:year:hour:min:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method is the designated intializer for the\
		File class. It initializes its Date superclass using the\
		
\b initFromDate:::
\b0  and 
\b setTime:::
\b0  methods. The file is assumed\
		to be local and so sets the localPath value to filename and\
		sourceHost to the value LocalHost. A remote file must indicate\
		this through the 
\b setSourceHost:
\b0  method.;\
	
\i0\ul Args:
\i\ulnone \
		filename: The full pathname to the file;\
		mode: The 10 char array with the UNIX style of file permissions;\
		size: The file size in bytes;\
		d: The day of the month, 1-31;\
		m: The month of the year, 1-12;\
		y: The year:\
				year <  100 => year = year + CurrentCentury\
				year >= 100 => year = year;\
		hour: The hour, 0-23;\
		min: The minute, 0-59;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 \
	[super initFromDate: d : m : y];\
	[super setTime: hour : min : 0];\
\
	localPath = NXCopyStringBuffer(filename);\
	sourceHost = LocalHost;\
	sourcePath = NULL;\
	bcopy(mode, fileMode, 10);\
	fileMode[10] = NIL;\
	fileSize = size;\
	emptyDir = NO;\
	fileInfo = [[FileInfo alloc] init];\
	if( [self isLink] == YES )\
		fileType = eLinkFile;\
	else if( [self isDirectory] == YES )\
		fileType = eDirectoryFile;\
	else\
		fileType = eRegularFile;\
	[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
	if( fileType == eDirectoryFile )\
	\{\
		sortKey = [[DirectorySortKey alloc] init];\
		[sortKey setValue: eSortByName];\
	\}\
\
	return self;\
\} 
\b0\i // End init: mode: size: day: month: year: hour: min:
\b\i0 \
\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 - free\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker6296 \markername free;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  [super free];\
	
\i0\ul Description:
\i\ulnone  This method frees the variables we allocate
\fc1\cf1 ;
\fc0\cf0 \
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc0\cf0 \

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\fc0\cf0 	free(sourcePath);\
	if( localPath != NULL )\
		free(localPath);\
	[fileInfo free];\
	[listing freeObjects];\
	[listing free];\
	[sortKey free];\
\
	return [super free];\
\} 
\b0\i // End free
\b\i0 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 \
- setSourceHost:(const char *) host\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker6627 \markername setSourceHost:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method sets the sourceHost instance variable.\
		Use of this message indicates that the File object is remote\
		to the host the app is on. As such, it assigns the localPath\
		value to sourcePath and sets localPath to NULL.;\
	
\i0\ul Args:
\i\ulnone \
		host: The name of the source host.  This is converted to\
			a unique string via 
\b NXUniqueString()
\b0 .;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	sourceHost = NXUniqueString(host);\
	if( sourceHost != LocalHost )\
	\{	
\b0\i /* Set the source path to the local path.  When the source host\
			is not local the local path can only be set by an operation\
			that brings the file to the local host. */
\b\i0 \
		sourcePath = localPath;\
		localPath = NULL;\
		[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
		[delegate updateWithInspectorInfo: fileInfo];\
	\}\
\
	return self;\
\} 
\b0\i // End setSourceHost:
\b\i0 \
\
- setDelegate: theDelegate\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker7528 \markername setDelegate:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method sets the File delegate;\
	
\i0\ul Args:
\i\ulnone \
		theDelegate: The new delegate;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	delegate = theDelegate;\
\
	return self;\
\} 
\b0\i // End setDelegate:
\b\i0 \
\
- loadDirectory: server\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker7756 \markername loadDirectory:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil otherwise;\
	
\i0\ul Description:
\i\ulnone  This method must be overriden by File subclasses.\
		File subclasses must not send this message to File since this\
		will cause an error to be generated.;\
	
\i0\ul Args:
\i\ulnone \
		server: An object which can provide the info neccessary to\
			load a File's directory. An example would be an FTP server.;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	[s
\fc1\cf1 elf subclassResponsibility: _cmd];\
\

\fc0\cf0 	return nil;\
\} 
\b0\i // End loadDirectory
\b\i0 \
\
- setDirLoading:(BOOL) flag\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker8240 \markername setDirLoading:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method sets the dirLoading flag to that of\
		the argument. The dirLoading flag indicates if a directory\
		file is currently waiting a reply from the delegate server.;\
	
\i0\ul Args:
\i\ulnone \
		flag: The Boolean value to assign dirLoading;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	dirLoading = flag;\
\
	return self;\
\} 
\b0\i\fc1\cf1 // End setDirLoading:
\b\i0\fc0\cf0 \
\
- setEmptyDir:(BOOL) flag\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker8618 \markername setEmptyDir:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method sets the emptyDir flag to that of\
		the argument. The emptyDir flag indicates if a directory\
		has been loaded and contains no files.;\
	
\i0\ul Args:
\i\ulnone \
		flag: The Boolean value to assign emptyDir;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	emptyDir = flag;\
\
	return self;\
\} 
\b0\i\fc1\cf1 // End setEmptyDir:
\b\i0\fc0\cf0 \
\
- setLinkTarget: target\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker8963 \markername setLinkTarget:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method sets linkTarget to the object given\
		by target.  target is expected to be a subclass of File.  The\
		linkTarget allows one to determine acquire additional info about\
		a File object that represents a link to another File.;\
	
\i0\ul Args:
\i\ulnone \
		linkTarget: The object (a File subclass) to assign linkTarget;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	linkTarget = target;\
\
	return self;\
\} 
\b0\i\fc1\cf1 // End setLinkTarget:
\b\i0\fc0\cf0 \
\

\b0\i\fs28 /*\\ ---------------------------------- Info Methods ---------------------------------- \\*/
\b\i0\fs24 \
\
static const char *FileDir(char *path)\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker9529 \markername FileDir;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul RoutineDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The location of the file given by path. NULL is\
		returned if path does not contain a '/' or is NULL.;\
	
\i0\ul Description:
\i\ulnone  This function extracts the parent directory name\
		from the fully qualified path and returns it as a new string.\
		The returned path includes the trailing '/'.;\
	
\i0\ul Args:
\i\ulnone \
		path: The full pathname of the file;\
*/\

\f0\b\i0 char *dir, 
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 *endOfPath, *tmpPtr, tmp_c
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0  = 0
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 ;\
\
	if( pa
\fc1\cf1 th == NULL )\
		return NULL;\
	dir =  malloc(strlen(path)+1);\
	strcpy(dir, pa
\fc0\cf0 th);\
	
\b0\i /* If the file is a link, temporarly truncate the file name prior to the "->" */
\b\i0 \
	tmpPtr = rindex(dir, '>');\
	if( tmpPtr != NULL )\
	\{\
		tmpPtr -= 2;\
		tmp_c = *tmpPtr;\
		*tmpPtr = '\\0';\
	\}\
	endOfPath = rindex(dir, '/');\
	if( endOfPath != NULL )\
	\{\
		endOfPath ++;\
		*endOfPath = NIL;\
	\}\
	if( tmpPtr != NULL )\
		*tmpPtr = tmp_c;\
\
	return dir;\
\} 
\b0\i // End FileDir
\b\i0 \
\

\b0\i /* The onl
\fc1\cf1 y unobvious o
\fc0\cf0 f the info methods are the sourceX versus localX\
	methods.  The localX versions check only the local versions of the instance\
	variables. The sourceX versions check use the local instance variables\
	if the 
\b isLocal
\b0  method returns YES, and the source instance variables\
	otherwise. */
\b\i0 \
- (const char *) localName\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker10725 \markername localName;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Name of file on local host
\b\i0\fc0\cf0 \
	return [self fileComponent: localPath removeLink: NO];\
\}\
- (const char *) sourceName;\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker10846 \markername sourceName;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Name of file on sourceHost
\b\i0\fc0\cf0 \
const char *name;\
\
	if( [self isLocal] == YES )\
		name = [self localName];\
	else\
		name = [self fileComponent: sourcePath removeLink: YES];\
	return name;\
\}\
- (const char *) sourceNameWithLink\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker11072 \markername sourceName;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Name of file on sourceHost including the link target
\b\i0\fc0\cf0 \
const char *name;\
\
	if( [self isLocal] == YES )\
		name = [self localName];\
	else\
		name = [self fileComponent: sourcePath removeLink: NO];\
	return name;\
\}\
- (const char *) localPathname\
\{ 
\b0\i\fc1\cf1 // 
{\b\i0\fc0\cf0{\NeXTHelpMarker11318 \markername localPathname;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\ulnone\fs24\fc0\cf0  
\b0\i\fc1\cf1 Full pathname of file on local host
\b\i0\fc0\cf0 \
	return localPath;\
\}\
- (const char *) sourcePathname\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker11414 \markername sourcePathname;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Full pathname of file on sourceHost
\b\i0\fc0\cf0 \
	if( [self isLocal] == YES )\
		return [self localPathname];\
	return sourcePath;\
\}\
- (const char *) localDirectory\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker11571 \markername localDirectory;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Full pathname of our parent directory on local host
\b\i0\fc0\cf0 \
	return FileDir(localPath);\
\}\
- (const char *) sourceDirectory\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker11693 \markername sourceDirectory;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Full pathname of our parent directory on sourceHost
\b\i0\fc0\cf0 \
	if( [self isLocal] == YES )\
		return [self localDirectory];\
	return FileDir(sourcePath);\
\}\
- (NXAtom) sourceHost\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker11866 \markername sourceHost;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  An NXAtom (unique string) for the hostname of the orginating host
\b\i0\fc0\cf0 \
	return sourceHost;\
\}\
- (const char *) modeString\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker11989 \markername modeString;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  The UNIX style of mode string
\b\i0\fc0\cf0 \
	return fileMode;\
\}\
- (int) mode\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12059 \markername mode;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  The octal representation of the fileMode. Does not handle setuid or setgid yet
\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\fc1\cf1 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 int mode, i, j;\
	mode = 0;\
	for(i = 1, j = 8; i < 10; i ++, j --)\
		if( fileMode[i] != '-' )\
			mode |= (1 << j);\
	return mode;\
\}\
- (BOOL) isDirectory\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12296 \markername isDirectory;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Do we represent a directory file?
\b\i0\fc0\cf0 \
	if( fileMode[0] == 'd' )\
		return YES;\
	else if( [self isLink] ==  YES )\
	\{\
		if( linkTarget != nil && linkTarget != self )\
			return [linkTarget isDirectory];\
	\}\
	return NO;\
\}\
- (BOOL) isLink\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12531 \markername isLink;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Do we represent a link to another file?
\b\i0\fc0\cf0 \
	if( fileMode[0] == 'l' )\
		return YES;\
	return NO;\
\}\
- (BOOL) isLocal\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12649 \markername isLocal;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Do we orginate from the local host?
\b\i0\fc0\cf0 \
	if( sourceHost == LocalHost )\
		return YES;\
	return NO;\
\}\
- (int) fileSize\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12768 \markername fileSize;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Size of the file in bytes
\b\i0\fc0\cf0 \
	return fileSize;\
\}\
- dirListing\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12834 \markername dirListing;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  The ObjectList for our directory items
\b\i0\fc0\cf0 \
	return listing;\
\}\
- (BOOL) dirLoading\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker12919 \markername dirLoading;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Are we obtaining our directory contents?
\b\i0\fc0\cf0 \
	return dirLoading;\
\}\
- (BOOL) emptyDir\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker13007 \markername emptyDir;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  Are we obtaining our directory contents?
\b\i0\fc0\cf0 \
	return emptyDir;\
\}\
- linkTarget\
\{ 
\b0\i\fc1\cf1 // 
{{\NeXTHelpMarker13088 \markername linkTarget;}
¬}\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b0\i\ulnone\fs24\fc1\cf1  The File object subclass we point to
\b\i0\fc0\cf0 \
	return linkTarget;\
\}\
- (DirectorySortKey *) sortKey\
\{\
	return sortKey;\
\}\

\b0\i\fs28 /*\\ ------------------------------- Local Manipulation Methods ------------------------------- \\*/
\b\i0\fs24 \
- (const char *) verifyPathname:(const char *) pathname\
	collisionWarnings:(BOOL) collisionWarnings\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker13404 \markername verifyPathname:collisionWarnings:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  A valid pathname if successful, NULL otherwise;\
	
\i0\ul Description:
\i\ulnone  This method is used to see if the pathname arg\
		exists. It lstat()s pathname, and if it exists it prompts\
		for a different name if collisionWarnings is YES. If pathname\
		does not exist, and lstat() returns the error ENOENT, meaning\
		a component does not exist, the method asks if the missing\
		components (directories) should be created. Currently it does\
		check to see if permissions allow the pathname it returns\
		to actually be created, read or wrote.;\
	
\i0\ul Args:
\i\ulnone \
		pathname: The pathname to check;\
		collisionWarnings: A flag indicating if a warning about existing\
			files should be displayed;\
*/
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 \
int statRtn;\
struct stat status;\
char tmpPath[MAXPATHLEN], *tmpPtr;\
SavePanel *savePanel;\
\
	
\b0\i /* Get the UNIX file info from the lstat(2) command */
\b\i0 \
	statRtn = lstat(pathname, &status);\
	if( statRtn == 0 && collisionWarnings == YES )\
	\{	
\b0\i\fc1\cf1 /* Ask the user if the file should be replaced */
\b\i0\fc0\cf0 \
		tmpPtr = rindex(pathname, '/');\
		if( tmpPtr != NULL )\
			tmpPtr ++;\
		else\
			tmpPtr = pathname;\
		statRtn = [self alert: "Create File" msg: "Replace existing %s?"\
			btn1: "Replace" btn2: "Save As..." btn3: "Cancel", tmpPtr];\
		switch( statRtn )\
		\{\
			case NX_ALERTDEFAULT:\
				break;\
			case NX_ALERTALTERNATE:\
				savePanel = [SavePanel new];\
				[sav
\fc1\cf1 ePanel setRequiredFileType: NULL];\
				[savePanel setTitle: "Create File"];\
				if( [savePanel runModal] == 0 )\
					return NULL;\
				pathname = [savePanel filename];\
				break;\

\fc0\cf0 			case NX_ALERTOTHER:\
			default:\
				return NULL;\
				break;\
		\}\
	\}\
	else if( statRtn == ENOENT )\
	\{	
\b0\i\fc1\cf1 /* At least one component of the path does not exist. Start at\
			top of the path and check each component for existence */
\b\i0\fc0\cf0 \
	char *end, *subpath;\
		strcpy(tmpPath, pathname);\
		end = index(tmpPath, '/');\
		if( end == tmpPath )\
		\{\
			end ++;\
			end = index(end, '/');\
		\}\
		*end = NIL;\
		while( access(tmpPath, F_OK) == 0 )\
		\{\
			*end = '/';\
			end ++;\
			end = index(end, '/');\
			if( end != NULL )\
				*end = NIL;\
		\}\
		
\b0\i\fc1\cf1 /* The last component of the path given by tmpPath does not exist.\
			Display the subpath that does not exist and ask the user if it\
			should be created */
\b\i0\fc0\cf0 \
		subpath = rindex(tmpPath, '/');\
		*end = '/';\
		end = rindex(tmpPath, '/');\
		if( end != subpath )\
			*end = NIL;\
		subpath ++;\
		
\b0\i\fc1\cf1 /* If the missing component is not the last component, prompt\
			user about subpath creation.  The final component is the\
			file. */
\b\i0\fc0\cf0 \
		if( index(subpath, '/') != NULL )\
		\{\
		char question[256];\
			sprintf(question, "A portion of the path that file [%s] %s%s: [%s]",\
				[self sourceName], "is being copied to does not exist\\n",\
				"\\tShould I create", subpath);\
			if( [self askYesNo:question cancel: NO] != NX_ALERTDEFAULT )\
				return NULL;\
			
\b0\i\fc1\cf1 /* The number of directories to create is equal to the number\
				of '/' chars in subpath */
\b\i0\fc0\cf0 \
			while( (end = index(subpath, '/')) != NULL )\
			\{	
\b0\i\fc1\cf1 /* Create the directory component */
\b\i0\fc0\cf0 \
				*end = NIL;\
				if( mkdir(tmpPath, 0755) != 0 )\
				\{\
					[self systemErr: "Failed to create directory: [%s]" method:_cmd,\
						tmpPath];\
					return NULL;\
				\}\
				*end = '/';\
				subpath = end + 1;\
			\}\
		\}\
	\}\
\
	return pathname;\
\} 
\b0\i\fc1\cf1 // End verifyPathname: collisionWarnings:
\b\i0\fc0\cf0 \
\
- createLocalFile:(NXStream *) stream path:(const char *) pathname\
	collisionWarnings:(BOOL) collisionWarnings\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker16774 \markername createLocalFile:path:collisionWarnings:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil otherwise;\
	
\i0\ul Description:
\i\ulnone  This method writes the NXStream to the file given by\
		pathname using NXSaveToFile().  If collisionWarnings is YES, we\
		ask before trashing existing files.;\
	
\i0\ul Args:
\i\ulnone \
		stream: The NXStream containing the file contents. If stream is NULL,\
			we just create an empty file.;\
		pathname: The pathname of the file to save the stream to;\
		collisionWarnings: A flag indicating if a panel should be displayed as\
			a warning if pathname exists;\
*/\
\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f0\b\i0\fc0\cf0 	
\b0\i\fc1\cf1 /* Verify the pathname */
\b\i0\fc0\cf0 \
	pathname = [self verifyPathname: pathname collisionWarnings: collisionWarnings];\
	if( pathname == NULL )\
		return nil;\
\

\f1\b0\fs20 [self debug: MAX_DEBUG method:_cmd, "Creating %s, %o", pathname, [self mode]];
\f0\b\fs24 \
	if( stream == NULL )\
	\{	
\b0\i\fc1\cf1 /* Just create the file */
\b\i0\fc0\cf0 \
	int tmpFileID;\
		if( [self isDirectory] == NO )\
		\{\
			tmpFileID = open(pat
\fc1\cf1 hname, O_CREAT | O_TRUNC);\
			if( tmpFileID < 0 )\
			\{\

\fc0\cf0 				[self systemErr: "Failed to create %s" method:_cmd, pathname];\
				return nil;\
			\}\
			close(tmpFileID);\
			if( chmod(pathname, [self mode]) < 0 )\
				[self systemErr: "Failed to set file mode %o" method:_cmd, [self mode]];\
		\}\
		else\
		\{\
			if( mkdir(pathname, [self mode]) < 0 )\

\fc1\cf1 			\{	
\b0\i /* Only report an error if it is not EEXIST, meaning the directory\
					already exists */
\b\i0 \
				if( errno != EEXIST )\
				\{\

\fc0\cf0 					[self systemErr: "Failed to create %s" method:_cmd, pathname];\
					return nil;\
				\}\
			\}\
		\}\
	\}\
	else\
	\{	
\b0\i /* Write the stream to the indicated file */
\b\i0 \
		if( NXSaveToFile(stream, pathname) == -1 )\

\fc1\cf1 		\{\

\fc0\cf0 			[self systemErr: "Failed to create %s" method:_cmd, pathname];\
			return nil;\
		\}\
		if( chmod(pathname, [self mode]) < 0 )\
		\{\
			[self systemErr: "Failed to set file mode %o" method:_cmd, [self mode]];\
			return nil;\
		\}\
	\}\
\
	
\b0\i\fc1\cf1 /* Assign our local path if it is not set */
\b\i0\fc0\cf0 \
	if( localPath == 0 )\
		localPath = NXCopyStringBuffer(pathname);\
	[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
	[delegate updateWithInspectorInfo: fileInfo];\
\
	return self;\
\} 
\b0\i\fc1\cf1 // End createLocalFile: path: collisionWarnings:
\b\i0\fc0\cf0 \
\
\
- copyFileTo:(const char *) targetPathname collisionWarnings:(BOOL) collisionWarnings\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker18968 \markername copyFileTo:collisionWarnings:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil otherwise;\
	
\i0\ul Description:
\i\ulnone  The method makes a duplicate of the UNIX file it\
		represents using the open(), read(), and write() routines;\
	
\i0\ul Args:
\i\ulnone \
		targetPathname: The pathname of the duplicate file;\
		collisionWarnings: A flag indicating if a warning should be\
			displayed if targetPathname exists;\
*/
\f0 \

\b\i0 int statRtn;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 struct stat status;\
char tmpPath[MAXPATHLEN];\
NXStream *fileStream;\
\
	if( localPath == NULL )\
		return nil;\
\
	
\b0\i /* Get the UNIX file info from the lstat(2) command */
\b\i0 \
	statRtn = lstat(targetPathname, &status);\
	if( statRtn == 0 && (status.st_mo
\fc1\cf1 de & S_IFDIR) )\
	\{	
\b0\i /* The target file is a directory, append our filename to the path */
\b\i0\fc0\cf0 \
		sprintf(tmpPath, targetPathname, [self localName]);\
		targetPathname = tmpPath;\
	\}\
\
	
\b0\i\fc1\cf1 /* Map our current file into memory and write it into the new target */
\b\i0\fc0\cf0 \
	fileStream = NXMapFile(localPath, NX_READWRITE);\
	if( fileStream == NULL )\
	\{\
		[self systemErr: "Failed to read %s" method:_cmd, localPath];\
		return nil;\
	\}\
	[self createLocalFile: fileStream path: targetPathname\
		collisionWarnings: collisionWarnings];\
	NXCloseMemory(fileStream, NX_FREEBUFFER);\
\
	return self;\
\} 
\b0\i\fc1\cf1 // End copyFileTo: collisionWarnings:
\b\i0\fc0\cf0 \
\
- moveFileTo:(const char *) targetPathname collisionWarnings:(BOOL) collisionWarnings\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker20279 \markername moveFileTo:collisionWarnings:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil otherwise;\
	
\i0\ul Description:
\i\ulnone  The method moves the UNIX file it\
		represents our 
\b copyFileTo:collisionWarnings:
\b0  method and\
		unlink(2) or DeleteDirectory() depding on if we are\
		a regular file or directory.;\
	
\i0\ul Args:
\i\ulnone \
		targetPathname: The pathname to move the file into;\
		collisionWarnings: A flag indicating if a warning should be\
			displayed if targetPathname exists;\
*/
\f0 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc0\cf0 	/* Not implemented yet */\
	[self notImplemented:_cmd];\
	[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
	[delegate updateWithInspectorInfo: fileInfo];\
\
	return self;\
\} 
\b0\i // End moveFileTo: collisionWarnings:
\b\i0 \
- linkFileTo:(const char *) targetPathname collisionWarnings:(BOOL) collisionWarnings\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker21049 \markername linkFileTo:collisionWarnings:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil otherwise;\
	
\i0\ul Description:
\i\ulnone  The method creates a link to the local UNIX file\
		given by targetPathname;\
	
\i0\ul Args:
\i\ulnone \
		targetPathname: The pathname to link to;\
		collisionWarnings: A flag indicating if a warning should be\
			displayed if targetPathname exists;\
*/
\f0 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc0\cf0 	/* Not implemented yet */\
	[self notImplemented:_cmd];\
	[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
	[delegate updateWithInspectorInfo: fileInfo];\
\
	return self;\
\} 
\b0\i // End linkFileTo: collisionWarnings:
\b\i0 \
\
- deleteFile:(BOOL) prompt\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker21648 \markername deleteFile:;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  [self free] if removed, self it canceled;\
	
\i0\ul Description:
\i\ulnone  This method removes the file from the file system\
		using the unlink(2) system call if it is not a directory,\
		or DeleteDirectory() if it is;\
	
\i0\ul Args:
\i\ulnone \
		prompt: A flag indicating if a panel should be displayed prior\
			to removing the file;\
*/\

\f0\b\i0 int action;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 char *tmpPtr;\
\
	if( prompt == YES )\
	\{	
\b0\i /* Ask the user if the file should be removed */
\b\i0 \
	char *msg = "Remove %s?";\
		tmpPtr = rindex(localPath, '/');\
		if( tmpPtr != NULL )\
			tmpPtr ++;\
		else\
			tmpPtr = localPath;\
		if( [self isDirectory] == YES )\
			msg = "Remove %s and its contents?";\
		action = [self alert: "Create File" msg: msg btn1: "Remove" btn2: "Cancel"\
			btn3: NULL, tmpPtr];\
		switch( action )\
		\{\
			case NX_ALERTDEFAULT:\
				break;\
			case NX_ALERTALTERNATE:\
			case NX_ALERTOTHER:\
			default:\
				return self;\
				break;\
		\}\
	\}\
\
	
\b0\i /* Check for directories */
\b\i0 \
	if( [self isDirectory] == NO )\
	\{\
		if( unlink(localPath) != 0 )\
		\{\
			[self systemErr: "Failed to unlink() %s" method:_cmd, localPath];\
			return self;\
		\}\
	\}\
	else\
	\{	
\b0\i /* Remove directory and its entries */
\b\i0 \
	char pathname[MAXPATHLEN];\
		strcpy(pathname, localPath);\
		if( DeleteDirectory(pathname) != 0 )\
		\{\
			[self systemErr: "Error while removing %s" method:_cmd, localPath];\
			return self;\
		\}\
	\}\
\
	return [self free];\
\} 
\b0\i // End deleteFile:(BOOL) prompt
\b\i0 \
\
- recycleFile\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker23056 \markername recycleFile;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self;\
	
\i0\ul Description:
\i\ulnone  This method asks the Workspace to recycle the file;\
*/\

\f0\b\i0 id <NXWorkspaceRequestProtocol> workspace;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 \

\fc0\cf0 	works
\fc1\cf1 pace = [Application workspace];\
	[workspace performFileOperation: WSM_RECYCLE_OPERATION\
		source: [self localDirectory] destination:"" files: [self localName]\
		options: NULL];\

\fc0\cf0 	
\b0\i /* Should message app delegate so they can delete us when the\
		operation is complete */
\b\i0 \
\
	return self;\
\} 
\b0\i // End recycleFile
\b\i0 \
\
\

\b0\i\fs28 /*\\ ---------------------- Display Methods ---------------------- \\*/
\b\i0\fs24 \
- (BOOL) openInWorkspace\
\{
\fc1\cf1 \

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc1\cf1 /*
{{\NeXTHelpMarker23623 \markername openInWorkspace;}
¬}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc1\cf1  --- 
\ul RoutineDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  YES if the file is opened, NO if not;\
	
\i0\ul Description:
\i\ulnone  This method invokes the NXWorkspaceRequestProtocol\
	method 
\b openFile:
\b0 , passing localPath as the arg.  If local\
	path is NULL, we send our delegate a createLocalFile: method\
	if it implements it. We return NO if the localPath is not\
	created. Otherwise, we return the result of the 
\b openFile:
\b0 \
	method.;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f0\b\i0\fc1\cf1 id <NXWorkspaceRequestProtocol> workspace;
\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc1\cf1 \
BOOL opened;\
\
	if( localPath == NULL )\
	\{\
		if( [delegate respondsTo: @selector(createLocalFile:)] == YES )\
			localPath = [delegate createLocalFile: self];\

\fc0\cf0 		[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath : localPath : fileType];\
		[delegate updateWithInspectorInfo: fileInfo];\

\fc1\cf1 	\}\
	if( localPath == NULL )\
		return NO;\
\

\fc0\cf0 	workspac
\fc1\cf1 e = [Application wo
\fc0\cf0 rkspace];\
	opened = [workspace openFile: localPath];\

\f1\b0\fs20 [self debug: MAX_DEBUG method:_cmd, "%s = %d", localPath, opened];
\f0\b\fs24 \
\
	return opened;\
\} 
\b0\i // End openInWorkspace
\b\i0 \
\

\b0\i\fs28 /*\\ --------------------- ObjectArchival Protocol Methods --------------------- \\*/
\b\i0\fs24 \
static inline char *ClassName() \{ return "File"; \}\
static inline long ArchiveVersion()\
\{\
long version;\
	version = 1000 * FILE_VERS + 10 * FILE_SUBVERS + FILE_TYPE;\
	return version;\
\}\
\
- readFromTStream:(NXTypedStream *) stream\
\{\

\pard\tx180\tx360\tx540\tx720\tx900\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker24906 \markername readFromTStream:;}
¬}\pard\tx180\tx360\tx540\tx720\tx900\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil on failure;\
	
\i0\ul Description:
\i\ulnone  This method unarchives a File object description from the\
		typed stream previously saved by the 
\b writeToTStream:
\b0  method.\
		The receiving File object must have been allocated and inited using\
		[[File alloc] init] or [[File alloc] 
\fc1\cf1 initFromTStream
\fc0\cf0 :].\
		If the object is sucessfully read from the stream, self is returned.\
		If an exception occurs the object is freed and nil is returned.;\
	
\i0\ul Args:
\i\ulnone  \
		stream: the typed stream from which to read the object;\
*/
\f0 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc0\cf0 const char *className;\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 List *tmpList;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 BOOL hasListing;\
long version;\
void *data1 = NULL, *data2 = NULL;\
\
NX_DURING\

\f1\b0\fs20 [self debug: SUPER_DEBUG method: _cmd, "class = %s; superclass = %s\\n",\
	[[self class] name], [[self superclass] name]];\
[self debug: SUPER_DEBUG method: _cmd, "\\tinstance = %s\\n", ClassName()];
\f0\b\fs24 \
\
	[super readFromTStream: stream];\
\
	
\b0\i /* First read the class name & archive version info */
\b\i0 \
	NXReadTypes(stream, "*i", &className, &version);\
	if( strcmp(className, ClassName()) != 0 )\
	\{\
		NXAllocErrorData(strlen(className)+1, &data1);\
		NXAllocErrorData(strlen(ClassName())+1, &data2);\
		strcpy(data1, className);\
		strcpy(data2, ClassName());\
		NX_RAISE(eWrongClassName, data1, data2);\
	\}\
\
	
\b0\i /* Unarchive our instance variables */
\b\i0 \
	switch( version )\
	\{\
		case FILE_VERSION_0:\
		case FILE_VERSION_1:\
			NXReadType(stream, "i", &fileSize);\
			NXReadArray(stream, "c", 11, fileMode);\
			NXReadType(stream, "%", &sourceHost);\
			NXReadType(stream, "*", &sourcePath);\
			NXReadType(stream, "*", &localPath);\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc0\cf0 			
\b0\i /* The next archive item should be a bool flag indicating\
				if we have a listing varible in the archive */
\b\i0 \
			NXReadType(stream, "c", &hasListing);\
			if( hasListing == YES )\
			\{\
			File *tmpObj;\
				if( version < FILE_VERSION_1 )\
				\{	
\b0\i /* Earlier versions used a List rather than ObjectList */
\b\i0 \
					tmpList = [[List alloc] initFromTStream: stream];\
					
\b0\i /* Create an ObjectList and transfer the elements from the List */
\b\i0 \
					listing =  [[ObjectList alloc] initCount: 0 sortAlgorithm: eShellSort\
						typeID: eStringType keyMethod: @selector(sourceName)];\
					while( (tmpO
\fc1\cf1 bj = [tmpList removeObjectAt: 0]) != nil )\
						[
\fc0\cf0 listing
\fc1\cf1  insertObject: tmpObj];
\fc0\cf0 \
					[tmpList free];\
				\}\
				else\
					listing = [[ObjectList alloc] initFromTStream: stream];\
			\}\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 			dirLoading = NO;\
			
\b0\i /* Set our InspectorInfo instance variables */
\b\i0 \
			fileInfo = [[FileInfo alloc] init];\
			if( [self isLink] == YES )\
				fileType = eLinkFile;\
			else if( [self isDirectory] == YES )\
				fileType = eDirectoryFile;\
			else\
				fileType = eRegularFile;\
			[fileInfo setValue: fileMode : fileSize : sourceHost : sourcePath\
				: localPath : fileType];\
			if( fileType == eDirectoryFile )\
			\{\
				sortKey = [[DirectorySortKey alloc] init];\
				[sortKey setValue: eSortByName];\
			\}\
			break;\
\
		default:\
			NXAllocErrorData(strlen([[self class] name])+1, &data1);\
			NXAllocErrorData(sizeof(long), &data2);\
			strcpy(data1, [[self class] name]);\
			*((long *) data2) = version;\
			NX_RAISE(eBadObjVersion, data1, data2);\
			break;\
	\}\
NX_HANDLER\
	NX_RERAISE();\
NX_ENDHANDLER\
\
	return self;\
\} 
\b0\i // End readFromTStream:
\b\i0 \
\

\f1\fc1\cf1 - writeToTStream:(NXTypedStream *) stream\
\{\

\pard\tx180\tx360\tx540\tx720\tx900\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker28110 \markername writeToTStream:;}
¬}\pard\tx180\tx360\tx540\tx720\tx900\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  self if successful, nil on failure;\
	
\i0\ul Description:
\i\ulnone  This method archives a File object description to the\
		typed stream.  If the object is sucessfully written to the stream,\
		 self is returned.  If an exception occurs it is reraised.;\
	
\i0\ul Args:
\i\ulnone  \
		stream: the typed stream to write the object to;\
*/
\f0 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\f1\b\i0\fc1\cf1 NXModalSession *theSession;\
Panel *alertPanel;\
const char *theMessage, *className;\
int userAction = NX_ALERTDEFAULT;\
BOOL hasListing;\
long version;\
\
	if( dirLoading == YES )\
	\{
\f0\fc0\cf0 	
\b0\i /* A thread is active asking a remote server for\
			the contents of this directory.  Bring up a modal\
			panel telling the user about the situation and loop until\
			the thread completes or the user cancels. */
\b\i0 \

\f1\fc1\cf1 		theMessage = "File is loading directory";\
		alertPanel = NXGetAlertPanel(NULL, theMessage,\
			"Continue", "Cancel", NULL);\
		theSession = [NXApp beginModalSession: NULL for: alertPanel];\
		while( dirLoading == YES )\
		\{\
			userAction = [NXApp runModalSession: theSession];\
			if( userAction != NX_RUNCONTINUES )\
				break;\
			cthread_yield();\
		\}\
		[NXApp endModalSession: theSession];\
		NXFreeAlertPanel(alertPanel);\
	\}\
	if( userAction == NX_ALERTALTERNATE )\
		return nil;\
\
NX_DURING
\f0\fc0\cf0 \

\f1\b0\fs20 [self debug: SUPER_DEBUG method: _cmd, "class = %s; superclass = %s\\n",\
	[[self class] name], [[self superclass] name]];\
[self debug: SUPER_DEBUG method: _cmd, "\\tinstance = %s\\n", ClassName()];
\f0\b\fs24 \
\
	
\b0\i /* Our superclass conforms to ObjectArchival so msg it */
\b\i0 \

\f1\fc1\cf1 	[super writeToTStream: stream];\
\

\f0\fc0\cf0 	
\b0\i /* Archive the class name & version */
\b\i0 \

\f1\fc1\cf1 	className = ClassName();\
	version = ArchiveVersion();\
	NXWriteTypes(stream, "*i", &className, &version);\
\

\f0\fc0\cf0 	
\b0\i\fc1\cf1 /* Archive our instance variables */
\b\i0\fc0\cf0 \

\f1\fc1\cf1 	NXWriteType(stream, "i", &fileSize);\
	NXWriteArray(stream, "c", 11, fileMode);\
	NXWriteType(stream, "%", &sourceHost);\
	NXWriteType(stream, "*", &sourcePath);\
	NXWriteType(stream, "*", &localPath);\
	if( dirLoading == YES || listing == nil )\
		hasListing = NO;\
	else\
		hasListing = YES;\
	NXWriteType(stream, "c", &hasListing);\
	if( hasListing == YES )\
		[listing writeToTStream: stream];\
NX_HANDLER\
	NX_RERAISE();\
NX_ENDHANDLER\
\
	return self;\
\}
\f0\fc0\cf0  
\b0\i // End writeToTStream:
\b\i0 \
\

\f1\fc1\cf1 /*\\ --------------- InspectorInfoUpdate Protocol Methods --------------- \\*/\
\
- (BOOL) updateWithInspectorInfo:(InspectorInfo *) theInfo\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker30404 \markername resolveLink:ftpd:;}
,}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  YES if we update from the info provided, NO otherwise;\
	
\i0\ul Description:
\i\ulnone  This method attempts to set update ourselves from the\
		value contained in. The type of value
\fc1\cf1  is determined by sending theInfo\
		an infoCode message. Files can take eDirectorySortKey & eFileInfo.
\fc0\cf0 ;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0 \
		theInfo: An InspectorInfo subclass;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc1\cf1 BOOL isDirectory;\
DirectorySortKey *theSortKey;\
ObjectList <ObjectArchival> *theListing;\
\
	isDirectory = [self isDirectory];\
\
	
\b0\i // Update the corresponding information
\b\i0  \
	switch( [theInfo infoCode] )\
	\{\
		case eDirectorySortKey:\
			if( isDirectory == NO )\
				return NO;\
			
\b0\i /* We need to figure out if we really are a directory or\
				just a link to a directory */
\b\i0 \
			theSortKey = sortKey;\
			theListing = listing;\
			if( [self isLink] == YES )\
			\{\
				theSortKey = [linkTarget sortKey];\
				theListing = [linkTarget dirListing];\
			\}\
			if( [theSortKey fastIsEqual: theInfo] == YES )\
				return NO;\
			
\b0\i // Resort our listing using the new key
\b\i0 \
			[theSortKey takeValueFrom: theInfo];\
			switch( [theSortKey sortKey] )\
			\{\
				case eSortByName:\
					[theListing setSortDirection: eSmallToLarge];\
					[theListing changeKeyMethod: @selector(sourceName)\
						typeID: eStringType];\
					break;\
				case eSortByInvName:\
					[theListing setSortDirection: eLargeToSmall];\
					[theListing changeKeyMethod: @selector(sourceName)\
						typeID: eStringType];\
					break;\
				case eSortBySize:\
					[theListing setSortDirection: eSmallToLarge];\
					[theListing changeKeyMethod: @selector(fileSize)\
						typeID: eIntType];\
					break;\
				case eSortByInvSize:\
					[theListing setSortDirection: eLargeToSmall];\
					[theListing changeKeyMethod: @selector(fileSize)\
						typeID: eIntType];\
					break;\
				case eSortByDate:\
					[theListing setSortDirection: eSmallToLarge];\
					[theListing changeKeyMethod: @selector(extendedDate)\
						typeID: eIntType];\
					break;\
				case eSortByInvDate:\
					[theListing setSortDirection: eLargeToSmall];\
					[theListing changeKeyMethod: @selector(extendedDate)\
						typeID: eIntType];\
					break;\
			\}\
			break;\
		case eFileInfo:\
			if( [fileInfo fastIsEqual: theInfo] == YES )\
				return NO;\
			[fileInfo takeValueFrom: theInfo];\
			break;\
		default:\
			return NO;\
			break;\
	\}\
\
	return YES;\
\} 
\b0\i // End updateWithInspectorInfo:
\b\i0 \
\
- (BOOL) getInspectorInfo: theInfo\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker32758 \markername resolveLink:ftpd:;}
,}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  YES if we can provide the requested info, NO otherwise;\
	
\i0\ul Description:
\i\ulnone  This method attempts to set theInfo to give theInfo\
		the value it is asking for. Thi
\fc1\cf1 s is determined by sending theInfo\
		an infoCode message. Files can give eDirectorySortKey & eFileInfo.
\fc0\cf0 ;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0 \
		theInfo: An InspectorInfo subclass;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc1\cf1 BOOL isDirectory;\
DirectorySortKey *theSortKey;\
\
	isDirectory = [self isDirectory];\
	switch( [theInfo infoCode] )\
	\{\
		case eDirectorySortKey:\
			theSortKey = sortKey;\
			if( isDirectory == NO )\
				return NO;\
			else if( [self isLink] == YES )\
				theSortKey = [linkTarget sortKey];\
			[theInfo takeValueFrom: theSortKey];\
		break;\
		case eFileInfo:\
			[theInfo takeValueFrom: fileInfo];\
		break;\
		default:\
			return NO;\
		break;\
	\}\
\
	return YES;\
\} 
\b0\i // End getInspectorInfo:
\f0\b\i0\fc0\cf0 \
\

\f1 - (const char *) linkTargetName:(BOOL) getFullPath\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker33636 \markername resolveLink:ftpd:;}
,}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The pathname of the link target of our link if we can\
		resolve it, 0 otherwise;\
	
\i0\ul Description:
\i\ulnone  This method constructs the pathname of a file's link target.\
		if getFullPath is YES it constructs a fully qualified pathname if\
		the link target is specified relative to the parent directory, e.g.,\
		"aLink -> ../../linkTarget".;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0 \
		getFullPath: Flag indicating if the returned path should be fully\
			qualified using our sourcePathname;\
*/\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\b\i0\fc0\cf0 static char fullPath[MAXPATHLEN];\
char *pathEnd;\
const char *parentDir, *targetName;\
\
	parentDir = [self sourcePathname];\
	targetName = strrchr(parentDir, '>');\
	if( targetName == 0 )\
		return 0;	
\b0\i\fc1\cf1 // Failed to find link ptr
\b\i0\fc0\cf0 \
	
\b0\i\fc1\cf1 // Locate the end of the source path
\b\i0\fc0\cf0 \
	strcpy(fullPath, parentDir);\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\fc1\cf1 	pathEnd = strrchr(fullPath, '>');\
	pathEnd[-1] = 0;\
	
\b0\i // Now back up to parent directory
\b\i0 \
	pathEnd = strrchr(fullPath, '/');\

\b0\i 	// Advance to target name, move past any leading white space & '>'
\b\i0\fc0\cf0 \
	targetName ++;\
	while( issp
\fc1\cf1 ace(*
\fc0\cf0 targetName
\fc1\cf1 ) && *
\fc0\cf0 targetName
\fc1\cf1  != '\\0' )\
		
\fc0\cf0 targetName
\fc1\cf1  ++;\
	if( *
\fc0\cf0 targetName == '\\0' )
\b0\i  
\b\i0 \
		return 0;	
\b0\i\fc1\cf1 // Failed to find
\fc0\cf0  link ptr
\b\i0 \
\

\b0\i\fc1\cf1 	// If this is a relative path, build the full path if asked
\b\i0\fc0\cf0 \

\fc1\cf1 	if( 
\fc0\cf0 getFullPath == YES && 
\fc1\cf1 *targetName != '/' 
\fc0\cf0 )\
	\{\
		if( 
\fc1\cf1 *targetName == '.'
\fc0\cf0  )\
		\{	// Backtrack through the dotdots and dots\
		int dots;
\b0\i\fc1\cf1 \

\b\i0 			dots = strspn(targetName, ".");\
			while( dots )\
			\{\
				if( dots == 1 )\
				\{\
					if( targetName[dots] != '/' )\
						dots = 0;\
					else\
					\{\
						targetName += (dots+1);\
						dots = strspn(targetName, ".");\
					\}\
				\}\
				else\
				\{	// Back up one level\
					pathEnd --;\
					while( *pathEnd != 0 && *pathEnd != '/' )\
						pathEnd --;\
					if( *pathEnd == 0 )\
						pathEnd ++;\
					targetName += (dots+1);\
					dots = strspn(targetName, ".");\
				\}\
			\}\
		\}\
		// Combine targetName to pathEnd to form the full path\
		pathEnd ++;\
		while( *targetName )\
			*pathEnd ++ = *targetName ++;\
		*pathEnd = 0;\
		targetName = fullPath;
\fc0\cf0 \
	\}\
	return targetName;\

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 \} 
\b0\i // End linkTargetName:
\b\i0 \

\f0 \

\f1\fc1\cf1 - fileFromPath:(const char *) subPath\
\{\

\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b0\i\fc0\cf0 /*
{{\NeXTHelpMarker35686 \markername resolveLink:ftpd:;}
,}\pard\tx180\tx360\tx540\tx720\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\f1\b0\i\ulnone\fs24\fc0\cf0  --- 
\ul MethodDescription
\ulnone \
	
\i0\ul ReturnValue:
\i\ulnone  The File object located at subPath it it exits, else nil;\
	
\i0\ul Description:
\i\ulnone  This method recursively searches its listing and children's\
		listing contents for the File whose sourcePathname equates to the\
		next component of subPath. This only applies to directory files or\
		links whose target is a directory.;\
	
\i0\ul\fc1\cf1 Args:
\i\ulnone\fc0\cf0 \
		subPath: A path relative to the our sourcePath;\
*/\

\pard\tx520\tx1060\tx1600\tx2120\tx2660\tx3200\tx3720\tx4260\tx4800\tx5320\b\i0\fc1\cf1 char childName[MAXPATHLEN], *childEnd;\
int childIndex;\
File *child;\
\
	if( strcmp([self sourceName], subPath) == 0 )\
		return self;\
	else if( [self isDirectory] == NO )\
		return nil;\
	else if( listing == nil )\
		return nil;\
\
	
\b0\i // If we are a link we just return our linkTarget's value
\b\i0 \
	if( [self isLink] == YES )\
		return [linkTarget fileFromPath: subPath];\
   \
	
\b0\i // Build path to the top component
\b\i0 \
	strcpy(childName, subPath);\
	childEnd = strchr(childName, '/');\
	if( childEnd != 0 )\
	\{	// Remove the trailing '/' from childPath\
		*childEnd = 0;\
	\}\
	
\b0\i // See if our listing contains an entry with this partial path
\b\i0 \
	childIndex = [listing binarySearchUsing: childName canFail: YES];\
	if( childIndex > 0 )\
		childIndex --;\
	child = [listing objectAt: childIndex];\
	if( child == nil || strcmp(childName, [child sourceName]) != 0 )\
		return nil;\
	
\b0\i /* This is a child of ours. Return the child if this is the end\
		of the path else we return our child's fileFromPath: value */
\b\i0 \
	if( childEnd == 0 || childEnd[1] == 0 )\
		return child;\
	*childEnd = '/';\
	subPath = childEnd + 1;\
\
	return [child fileFromPath: subPath];
\b0\i\fc0\cf0 \

\f0\b\i0 \} 
\b0\i // End fileFromPath:
\b\i0 \

\pard\tx480\tx960\tx1440\tx1920\tx2400\tx2880\tx3360\tx3840\tx4320\tx4800\fc0\cf0 \
@end\
\

\pard\tx1140\tx2300\tx3440\tx4600\tx5760\tx6900\tx8060\tx9200\tx10360\tx11520\b0\i\fc1\cf1 /* RCS Information:\
	$Author: me $;\
	$Date: 94/01/08 14:40:05 $;\
	$Revision: 1.1 $;\
*/\

}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.