This is DirArray.m in view mode; [Download] [Up]
//============================================================================= // // Copyright (C) 1995-1997 by Paul S. McCarthy and Eric Sunshine. // Written by Paul S. McCarthy and Eric Sunshine. // All Rights Reserved. // // This notice may not be removed from this source code. // // This object is included in the MiscKit by permission from the authors // and its use is governed by the MiscKit license, found in the file // "License.rtf" in the MiscKit distribution. Please refer to that file // for a list of all applicable permissions and restrictions. // //============================================================================= //----------------------------------------------------------------------------- // DirArray.m // // An extensible array of directory entries. // //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // $Id: DirArray.m,v 1.2 97/06/10 04:53:13 sunshine Exp $ // $Log: DirArray.m,v $ // Revision 1.2 97/06/10 04:53:13 sunshine // v15: Upgraded naming. Fixed bug: Wasn't taking sticky-bit into account // when computing canToggleLock. // // Revision 1.1 97/02/05 08:22:38 sunshine // v13: Synchronized with ScrollDir (v29). Added unscaledImage. Added // isLocked & canToggleLock. Added manipulation methods. Supports file // renaming. //----------------------------------------------------------------------------- #import "DirArray.h" #import <appkit/Application.h> #import <appkit/NXImage.h> #import <appkit/workspaceRequest.h> #import <assert.h> #import <errno.h> #import <libc.h> #import <unistd.h> #ifdef _POSIX_SOURCE # define GRP_TYPE gid_t # define MAX_GRPS NGROUPS_MAX #else # define GRP_TYPE int # define MAX_GRPS NGROUPS #endif @implementation DirArray //----------------------------------------------------------------------------- // safeStrdup //----------------------------------------------------------------------------- - (char*)safeStrdup:(char const*)s { char* t = 0; if (s != 0) t = NXCopyStringBufferFromZone( s, [self zone] ); return t; } //----------------------------------------------------------------------------- // safeFree //----------------------------------------------------------------------------- - (void)safeFree:(void*)p { if (p != 0) NXZoneFree( [self zone], p ); } //----------------------------------------------------------------------------- // dirWritable: //----------------------------------------------------------------------------- - (BOOL)dirWritable:(char const*)path { BOOL rc = NO; struct stat st; if (stat( path, &st ) == 0) { unsigned int mode = st.st_mode; if ((mode & 0002) != 0 || // "other" ((mode & 0200) != 0 && st.st_uid == geteuid())) // "owner" rc = YES; else if ((mode & 0020) != 0) // "group" { gid_t const gid = getegid(); if (st.st_gid == gid) rc = YES; else { GRP_TYPE groups[ MAX_GRPS ]; int n = getgroups( MAX_GRPS, groups ); while (n-- > 0) if (gid == groups[n]) { rc = YES; break; } } } } return rc; } //----------------------------------------------------------------------------- // dirSticky: //----------------------------------------------------------------------------- - (BOOL)dirSticky:(char const*)path { struct stat st; if (stat( path, &st ) == 0) return ((st.st_mode & 01000) != 0); return NO; } //----------------------------------------------------------------------------- // dirEntryCons:name:path:isDotDot: //----------------------------------------------------------------------------- - (void)dirEntryCons:(DirEntry*)de name:(char const*)n path:(char const*)path isDotDot:(BOOL)dotdot { int rc; memset( de, 0, sizeof(*de) ); de->dir = self; de->name = [self safeStrdup:n]; if ((rc = lstat( path, &(de->status) )) == 0) { unsigned int mode = de->status.st_mode; if ((mode & S_IFMT) == S_IFLNK) // soft-link? { char symbuf[ FILENAME_MAX + 1 ]; int cc = readlink( path, symbuf, FILENAME_MAX ); if (cc >= 0) { struct stat st; symbuf[ cc ] = '\0'; de->softLink = [self safeStrdup:symbuf]; if (stat( path, &st ) == 0) mode = st.st_mode; // mode of file linked to } } de->isDirectory = ((mode & S_IFMT) == S_IFDIR); } de->canToggleLock = (!dotdot && [self dirWritable] && (!sticky || de->status.st_uid == effectiveUid)); de->isLocked = !de->canToggleLock; } //----------------------------------------------------------------------------- // freeImage //----------------------------------------------------------------------------- - (void)freeImage:(NXImage*)p { if (p != 0) [p free]; } //----------------------------------------------------------------------------- // dirEntryDestroy: //----------------------------------------------------------------------------- - (void)dirEntryDestroy:(DirEntry*)de { [self freeImage:de->scaledImage]; [self freeImage:de->unscaledImage]; [self safeFree:de->name]; [self safeFree:de->softLink]; } //----------------------------------------------------------------------------- // entryAt: //----------------------------------------------------------------------------- - (DirEntry const*)entryAt:(int)n { assert( 0 <=n && n < numEntries ); return (entries + n); } //----------------------------------------------------------------------------- // isDir: //----------------------------------------------------------------------------- - (BOOL)isDir:(DirEntry const*)de { return de->isDirectory; } //----------------------------------------------------------------------------- // isDirAt: //----------------------------------------------------------------------------- - (BOOL)isDirAt:(int)n { return [self isDir:[self entryAt:n]]; } //----------------------------------------------------------------------------- // canToggleLock: //----------------------------------------------------------------------------- - (BOOL)canToggleLock:(DirEntry const*)de { return de->canToggleLock; } //----------------------------------------------------------------------------- // canToggleLockAt: //----------------------------------------------------------------------------- - (BOOL)canToggleLockAt:(int)n { return [self canToggleLock:[self entryAt:n]]; } //----------------------------------------------------------------------------- // isLocked: //----------------------------------------------------------------------------- - (BOOL)isLocked:(DirEntry const*)de { return de->isLocked; } //----------------------------------------------------------------------------- // isLockedAt: //----------------------------------------------------------------------------- - (BOOL)isLockedAt:(int)n { return [self isLocked:[self entryAt:n]]; } //----------------------------------------------------------------------------- // setLocked:at: //----------------------------------------------------------------------------- - (void)setLocked:(BOOL)flag at:(int)n { assert( entries[n].canToggleLock ); entries[n].isLocked = flag; } //----------------------------------------------------------------------------- // setName:at: //----------------------------------------------------------------------------- - (void)setName:(char const*)s at:(int)n { [self safeFree:entries[n].name]; entries[n].name = [self safeStrdup:s]; } //----------------------------------------------------------------------------- // loadImage: //----------------------------------------------------------------------------- - (void)loadImage:(DirEntry*)de { char buff[ FILENAME_MAX + 1 ]; char const* const dir_part = de->dir->name; int const dirlen = strlen( dir_part ); memcpy( buff, dir_part, dirlen ); strcpy( buff + dirlen, de->name ); de->unscaledImage = [[Application workspace] getIconForFile:buff]; de->scaledImage = [de->unscaledImage copy]; [de->scaledImage setScalable:YES]; } //----------------------------------------------------------------------------- // getImage:scaled: //----------------------------------------------------------------------------- - (NXImage*)getImage:(DirEntry const*)de scaled:(BOOL)wantsScaled { if (de->unscaledImage == 0) [self loadImage:(DirEntry*)de]; return (wantsScaled ? de->scaledImage : de->unscaledImage); } //----------------------------------------------------------------------------- // getImageAt:scaled: //----------------------------------------------------------------------------- - (NXImage*)getImageAt:(int)n scaled:(BOOL)flag { return [self getImage:[self entryAt:n] scaled:flag]; } //----------------------------------------------------------------------------- // init //----------------------------------------------------------------------------- - (id)init { [super init]; totalBytes = 0; numEntries = 0; maxEntries = 0; entries = 0; writable = NO; sticky = NO; effectiveUid = geteuid(); return self; } //----------------------------------------------------------------------------- // empty //----------------------------------------------------------------------------- - (void)empty { DirEntry* p; for (p = entries + numEntries; p != entries; ) [self dirEntryDestroy:--p]; numEntries = 0; totalBytes = 0; } //----------------------------------------------------------------------------- // free //----------------------------------------------------------------------------- - (id)free { [self empty]; [self safeFree:name]; [self safeFree:entries]; return [super free]; } //----------------------------------------------------------------------------- // count //----------------------------------------------------------------------------- - (int)count { return numEntries; } //----------------------------------------------------------------------------- // totalBytes //----------------------------------------------------------------------------- - (size_t)totalBytes { return totalBytes; } //----------------------------------------------------------------------------- // dirWritable //----------------------------------------------------------------------------- - (BOOL)dirWritable { return writable; } //----------------------------------------------------------------------------- // dirSticky //----------------------------------------------------------------------------- - (BOOL)dirSticky { return sticky; } //----------------------------------------------------------------------------- // remove: //----------------------------------------------------------------------------- - (void)remove:(int)n { if (0 <= n && n < numEntries) { DirEntry* p = entries + n; totalBytes -= p->status.st_size; numEntries--; [self dirEntryDestroy:p]; if (n < numEntries) memmove( p, p + 1, (numEntries - n) * sizeof(*p) ); } } //----------------------------------------------------------------------------- // expand //----------------------------------------------------------------------------- - (void)expand { DirEntry* p = entries; int N = maxEntries; if (N == 0) { N = 16; p = (DirEntry*) NXZoneMalloc( [self zone], N * sizeof(*p) ); } else { N += N; p = (DirEntry*) NXZoneRealloc( [self zone], p, N * sizeof(*p) ); } maxEntries = N; entries = p; } //----------------------------------------------------------------------------- // addName:path:isDotDot: //----------------------------------------------------------------------------- - (void)addName:(char const*)n path:(char const*)fullpath isDotDot:(BOOL)dotdot { DirEntry* p; if (numEntries >= maxEntries) [self expand]; p = entries + numEntries++; [self dirEntryCons:p name:n path:fullpath isDotDot:dotdot]; totalBytes += p->status.st_size; } //----------------------------------------------------------------------------- // loadPath:showHidden: //----------------------------------------------------------------------------- - (int)loadPath:(char const*)path showHidden:(BOOL)showHidden { int rc = 0; int dirlen; DIR* dirp; char namebuff[ FILENAME_MAX + 1 ]; dirlen = strlen( path ); strcpy( namebuff, path ); if (dirlen == 0 || namebuff[ dirlen - 1 ] != '/') { namebuff[ dirlen++ ] = '/'; namebuff[ dirlen ] = '\0'; } [self empty]; [self safeFree:name]; name = [self safeStrdup:namebuff]; writable = [self dirWritable:path]; sticky = [self dirSticky:path]; if ((dirp = opendir( path )) != 0) { struct direct const* dp; while ((dp = readdir(dirp)) != 0) { // Do not include the "." (self) entry. int const len = dp->d_namlen; char const* const nam = dp->d_name; BOOL const dot_name = (nam[0] == '.'); BOOL const dot_dot_name = (dot_name && len == 2 && nam[1] == '.'); if ((len > 1 || !dot_name) && // exclude "." (showHidden || !dot_name || dot_dot_name)) // include ".." { memcpy( namebuff + dirlen, nam, len + 1 ); [self addName:nam path:namebuff isDotDot:dot_dot_name]; } } closedir( dirp ); } else rc = errno; return rc; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.