2005-02-02 09:43:29 +00:00
|
|
|
|
/**
|
1997-03-03 20:10:10 +00:00
|
|
|
|
NSFileManager.m
|
|
|
|
|
|
2002-09-16 15:07:40 +00:00
|
|
|
|
Copyright (C) 1997-2002 Free Software Foundation, Inc.
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
|
|
|
|
Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
|
|
|
|
|
Author: Ovidiu Predescu <ovidiu@net-community.com>
|
|
|
|
|
Date: Feb 1997
|
1999-06-22 05:41:09 +00:00
|
|
|
|
Updates and fixes: Richard Frith-Macdonald
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2001-04-19 22:09:25 +00:00
|
|
|
|
Author: Nicola Pero <n.pero@mi.flashnet.it>
|
|
|
|
|
Date: Apr 2001
|
|
|
|
|
Rewritten NSDirectoryEnumerator
|
|
|
|
|
|
2005-11-06 08:43:44 +00:00
|
|
|
|
Author: Richard Frith-Macdonald <rfm@gnu.org>
|
2002-09-16 15:07:40 +00:00
|
|
|
|
Date: Sep 2002
|
|
|
|
|
Rewritten attribute handling code
|
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
|
|
|
License along with this library; if not, write to the Free
|
2005-05-22 03:32:16 +00:00
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
|
|
<title>NSFileManager class reference</title>
|
|
|
|
|
$Date$ $Revision$
|
1997-03-03 20:10:10 +00:00
|
|
|
|
*/
|
|
|
|
|
|
2005-06-04 05:01:01 +00:00
|
|
|
|
#define _FILE_OFFSET_BITS 64
|
|
|
|
|
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "config.h"
|
2003-07-31 23:49:32 +00:00
|
|
|
|
#include "GNUstepBase/preface.h"
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "Foundation/NSFileManager.h"
|
|
|
|
|
#include "Foundation/NSException.h"
|
|
|
|
|
#include "Foundation/NSAutoreleasePool.h"
|
|
|
|
|
#include "Foundation/NSLock.h"
|
|
|
|
|
#include "Foundation/NSDebug.h"
|
|
|
|
|
#include "Foundation/NSProcessInfo.h"
|
|
|
|
|
#include "Foundation/NSEnumerator.h"
|
|
|
|
|
#include "Foundation/NSSet.h"
|
2006-02-21 07:51:17 +00:00
|
|
|
|
#include "Foundation/NSBundle.h"
|
2002-10-14 08:52:39 +00:00
|
|
|
|
#include "GSPrivate.h"
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
#include <string.h>
|
1998-02-05 22:06:20 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
/* determine directory reading files */
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_DIRENT_H)
|
|
|
|
|
# include <dirent.h>
|
|
|
|
|
#elif defined(HAVE_SYS_DIR_H)
|
|
|
|
|
# include <sys/dir.h>
|
|
|
|
|
#elif defined(HAVE_SYS_NDIR_H)
|
|
|
|
|
# include <sys/ndir.h>
|
|
|
|
|
#elif defined(HAVE_NDIR_H)
|
|
|
|
|
# include <ndir.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_UNISTD_H
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#include <unistd.h>
|
2002-02-20 06:42:05 +00:00
|
|
|
|
#endif
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_WINDOWS_H
|
2000-09-13 03:51:30 +00:00
|
|
|
|
# include <windows.h>
|
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2002-05-10 12:23:32 +00:00
|
|
|
|
#include <stdio.h>
|
2006-02-17 06:31:04 +00:00
|
|
|
|
#include <tchar.h>
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#include <wchar.h>
|
2006-02-17 06:31:04 +00:00
|
|
|
|
#include <accctrl.h>
|
|
|
|
|
#include <aclapi.h>
|
1999-05-05 18:45:52 +00:00
|
|
|
|
#define WIN32ERR ((DWORD)0xFFFFFFFF)
|
|
|
|
|
#endif
|
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
/* determine filesystem max path length */
|
|
|
|
|
|
2000-09-13 03:51:30 +00:00
|
|
|
|
#if defined(_POSIX_VERSION) || defined(__WIN32__)
|
1997-03-03 20:10:10 +00:00
|
|
|
|
# include <limits.h> /* for PATH_MAX */
|
2005-10-11 19:09:26 +00:00
|
|
|
|
# if defined(__MINGW32__)
|
2000-09-13 03:51:30 +00:00
|
|
|
|
# include <sys/utime.h>
|
|
|
|
|
# else
|
|
|
|
|
# include <utime.h>
|
|
|
|
|
# endif
|
1999-05-05 18:45:52 +00:00
|
|
|
|
#else
|
2002-05-02 21:22:06 +00:00
|
|
|
|
# ifdef HAVE_SYS_PARAM_H
|
2000-09-13 03:51:30 +00:00
|
|
|
|
# include <sys/param.h> /* for MAXPATHLEN */
|
|
|
|
|
# endif
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
|
|
|
|
#ifndef PATH_MAX
|
|
|
|
|
# ifdef _POSIX_VERSION
|
|
|
|
|
# define PATH_MAX _POSIX_PATH_MAX
|
|
|
|
|
# else
|
|
|
|
|
# ifdef MAXPATHLEN
|
|
|
|
|
# define PATH_MAX MAXPATHLEN
|
|
|
|
|
# else
|
|
|
|
|
# define PATH_MAX 1024
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* determine if we have statfs struct and function */
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_VFS_H
|
|
|
|
|
# include <sys/vfs.h>
|
2002-10-28 09:28:55 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_STATVFS_H
|
|
|
|
|
# include <sys/statvfs.h>
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_STATFS_H
|
|
|
|
|
# include <sys/statfs.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SYS_FILE_H
|
1998-02-05 22:06:20 +00:00
|
|
|
|
#include <sys/file.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SYS_MOUNT_H
|
1999-05-06 13:58:19 +00:00
|
|
|
|
#include <sys/mount.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#include <errno.h>
|
1997-09-13 17:52:31 +00:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_STAT_H
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#include <sys/stat.h>
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
1998-02-05 22:06:20 +00:00
|
|
|
|
#include <fcntl.h>
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_PWD_H
|
1998-04-20 14:13:19 +00:00
|
|
|
|
#include <pwd.h> /* For struct passwd */
|
|
|
|
|
#endif
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_GRP_H
|
1998-12-03 16:49:25 +00:00
|
|
|
|
#include <grp.h> /* For struct group */
|
|
|
|
|
#endif
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_UTIME_H
|
1998-02-05 22:06:20 +00:00
|
|
|
|
# include <utime.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
/*
|
|
|
|
|
* On systems that have the O_BINARY flag, use it for a binary copy.
|
|
|
|
|
*/
|
|
|
|
|
#if defined(O_BINARY)
|
|
|
|
|
#define GSBINIO O_BINARY
|
|
|
|
|
#else
|
|
|
|
|
#define GSBINIO 0
|
|
|
|
|
#endif
|
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
/* include usual headers */
|
|
|
|
|
|
2003-06-07 01:24:41 +00:00
|
|
|
|
#include "Foundation/NSArray.h"
|
|
|
|
|
#include "Foundation/NSDictionary.h"
|
|
|
|
|
#include "Foundation/NSData.h"
|
|
|
|
|
#include "Foundation/NSDate.h"
|
|
|
|
|
#include "Foundation/NSString.h"
|
|
|
|
|
#include "Foundation/NSValue.h"
|
|
|
|
|
#include "Foundation/NSPathUtilities.h"
|
|
|
|
|
#include "Foundation/NSFileManager.h"
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2005-06-04 07:22:51 +00:00
|
|
|
|
@interface NSDirectoryEnumerator (Local)
|
|
|
|
|
- (id) initWithDirectoryPath: (NSString*)path
|
|
|
|
|
recurseIntoSubdirectories: (BOOL)recurse
|
|
|
|
|
followSymlinks: (BOOL)follow
|
|
|
|
|
justContents: (BOOL)justContents
|
|
|
|
|
for: (NSFileManager*)mgr;
|
|
|
|
|
@end
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Macros to handle unichar filesystem support.
|
|
|
|
|
*/
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
|
|
|
|
#define _CHMOD(A,B) _wchmod(A,B)
|
|
|
|
|
#define _CLOSEDIR(A) _wclosedir(A)
|
|
|
|
|
#define _OPENDIR(A) _wopendir(A)
|
|
|
|
|
#define _READDIR(A) _wreaddir(A)
|
|
|
|
|
#define _RENAME(A,B) _wrename(A,B)
|
|
|
|
|
#define _RMDIR(A) _wrmdir(A)
|
|
|
|
|
#define _STAT(A,B) _wstat(A,B)
|
|
|
|
|
#define _UTIME(A,B) _wutime(A,B)
|
|
|
|
|
|
|
|
|
|
#define _CHAR unichar
|
|
|
|
|
#define _DIR _WDIR
|
|
|
|
|
#define _DIRENT _wdirent
|
|
|
|
|
#define _STATB _stat
|
|
|
|
|
#define _UTIMB _utimbuf
|
|
|
|
|
|
|
|
|
|
#define _NUL L'\0'
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
#define _CHMOD(A,B) chmod(A,B)
|
|
|
|
|
#define _CLOSEDIR(A) closedir(A)
|
|
|
|
|
#define _OPENDIR(A) opendir(A)
|
|
|
|
|
#define _READDIR(A) readdir(A)
|
|
|
|
|
#define _RENAME(A,B) rename(A,B)
|
|
|
|
|
#define _RMDIR(A) rmdir(A)
|
|
|
|
|
#define _STAT(A,B) stat(A,B)
|
|
|
|
|
#define _UTIME(A,B) utime(A,B)
|
|
|
|
|
|
|
|
|
|
#define _CHAR char
|
|
|
|
|
#define _DIR DIR
|
|
|
|
|
#define _DIRENT dirent
|
|
|
|
|
#define _STATB stat
|
|
|
|
|
#define _UTIMB utimbuf
|
|
|
|
|
|
|
|
|
|
#define _NUL '\0'
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-06-04 18:58:05 +00:00
|
|
|
|
#define _CCP const _CHAR*
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2002-09-16 13:23:09 +00:00
|
|
|
|
/*
|
2002-09-16 11:30:22 +00:00
|
|
|
|
* GSAttrDictionary is a private NSDictionary subclass used to
|
|
|
|
|
* handle file attributes efficiently ... using lazy evaluation
|
|
|
|
|
* to ensure that we only do the minimum work necessary at any time.
|
|
|
|
|
*/
|
|
|
|
|
@interface GSAttrDictionary : NSDictionary
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _STATB statbuf;
|
2006-02-18 20:53:01 +00:00
|
|
|
|
_CHAR _path[0];
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
|
|
|
|
|
traverseLink: (BOOL)traverse;
|
2002-09-16 11:30:22 +00:00
|
|
|
|
@end
|
|
|
|
|
|
2002-09-16 13:23:09 +00:00
|
|
|
|
/*
|
2002-09-16 11:30:22 +00:00
|
|
|
|
* We also need a special enumerator class to enumerate the dictionary.
|
|
|
|
|
*/
|
|
|
|
|
@interface GSAttrDictionaryEnumerator : NSEnumerator
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *dictionary;
|
|
|
|
|
NSEnumerator *enumerator;
|
|
|
|
|
}
|
|
|
|
|
+ (NSEnumerator*) enumeratorFor: (NSDictionary*)d;
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1998-02-05 22:06:20 +00:00
|
|
|
|
@interface NSFileManager (PrivateMethods)
|
|
|
|
|
|
|
|
|
|
/* Copies the contents of source file to destination file. Assumes source
|
|
|
|
|
and destination are regular files or symbolic links. */
|
1999-06-18 10:28:11 +00:00
|
|
|
|
- (BOOL) _copyFile: (NSString*)source
|
|
|
|
|
toFile: (NSString*)destination
|
|
|
|
|
handler: (id)handler;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
|
|
|
|
/* Recursively copies the contents of source directory to destination. */
|
1999-06-18 10:28:11 +00:00
|
|
|
|
- (BOOL) _copyPath: (NSString*)source
|
|
|
|
|
toPath: (NSString*)destination
|
|
|
|
|
handler: (id)handler;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
2003-04-17 11:23:29 +00:00
|
|
|
|
/* Recursively links the contents of source directory to destination. */
|
|
|
|
|
- (BOOL) _linkPath: (NSString*)source
|
|
|
|
|
toPath: (NSString*)destination
|
|
|
|
|
handler: handler;
|
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
/* encapsulates the will Process check for existence of selector. */
|
|
|
|
|
- (void) _sendToHandler: (id) handler
|
|
|
|
|
willProcessPath: (NSString*) path;
|
|
|
|
|
|
|
|
|
|
/* methods to encapsulates setting up and calling the handler
|
|
|
|
|
in case of an error */
|
|
|
|
|
- (BOOL) _proceedAccordingToHandler: (id) handler
|
|
|
|
|
forError: (NSString*) error
|
|
|
|
|
inPath: (NSString*) path;
|
|
|
|
|
|
|
|
|
|
- (BOOL) _proceedAccordingToHandler: (id) handler
|
|
|
|
|
forError: (NSString*) error
|
|
|
|
|
inPath: (NSString*) path
|
2005-11-06 08:43:44 +00:00
|
|
|
|
fromPath: (NSString*) fromPath
|
2003-02-11 10:26:17 +00:00
|
|
|
|
toPath: (NSString*) toPath;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1998-02-05 22:06:20 +00:00
|
|
|
|
@end /* NSFileManager (PrivateMethods) */
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* This is the main class for platform-independent management of the local
|
|
|
|
|
* filesystem, which allows you to read and save files, create/list
|
|
|
|
|
* directories, and move or delete files and directories. In addition to
|
|
|
|
|
* simply listing directories, you may obtain an [NSDirectoryEnumerator]
|
|
|
|
|
* instance for recursive directory contents enumeration.
|
1997-03-03 20:10:10 +00:00
|
|
|
|
*/
|
|
|
|
|
@implementation NSFileManager
|
|
|
|
|
|
|
|
|
|
// Getting the default manager
|
|
|
|
|
|
|
|
|
|
static NSFileManager* defaultManager = nil;
|
2005-06-04 18:58:05 +00:00
|
|
|
|
static NSStringEncoding defaultEncoding;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a shared default file manager which may be used throughout an
|
|
|
|
|
* application.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
+ (NSFileManager*) defaultManager
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2002-09-10 21:53:34 +00:00
|
|
|
|
if (defaultManager == nil)
|
1997-09-13 17:52:31 +00:00
|
|
|
|
{
|
|
|
|
|
NS_DURING
|
|
|
|
|
{
|
|
|
|
|
[gnustep_global_lock lock];
|
2002-09-10 21:53:34 +00:00
|
|
|
|
if (defaultManager == nil)
|
|
|
|
|
{
|
|
|
|
|
defaultManager = [[self alloc] init];
|
|
|
|
|
}
|
1997-09-13 17:52:31 +00:00
|
|
|
|
[gnustep_global_lock unlock];
|
|
|
|
|
}
|
|
|
|
|
NS_HANDLER
|
|
|
|
|
{
|
|
|
|
|
// unlock then re-raise the exception
|
|
|
|
|
[gnustep_global_lock unlock];
|
|
|
|
|
[localException raise];
|
|
|
|
|
}
|
|
|
|
|
NS_ENDHANDLER
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
1997-09-13 17:52:31 +00:00
|
|
|
|
return defaultManager;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-06-04 18:58:05 +00:00
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
|
|
|
|
defaultEncoding = [NSString defaultCStringEncoding];
|
|
|
|
|
}
|
|
|
|
|
|
1999-06-18 10:28:11 +00:00
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
TEST_RELEASE(_lastError);
|
1999-06-18 10:28:11 +00:00
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Changes the current directory used for all subsequent operations.<br />
|
|
|
|
|
* All non-absolute paths are interpreted relative to this directory.<br />
|
|
|
|
|
* The current directory is set on a per-task basis, so the current
|
|
|
|
|
* directory for other file manager instances will also be changed
|
|
|
|
|
* by this method.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) changeCurrentDirectoryPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2006-02-21 07:51:17 +00:00
|
|
|
|
static Class bundleClass = 0;
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR *lpath = [self fileSystemRepresentationWithPath: path];
|
2006-02-21 07:51:17 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* On some systems the only way NSBundle can determine the path to the
|
|
|
|
|
* executable is by searching for it ... so it needs to know what was
|
|
|
|
|
* the current directory at launch time ... so we must make sure it is
|
|
|
|
|
* initialised before we change the current directory.
|
|
|
|
|
*/
|
|
|
|
|
if (bundleClass == 0)
|
|
|
|
|
{
|
|
|
|
|
bundleClass = [NSBundle class];
|
|
|
|
|
}
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-11-05 16:20:19 +00:00
|
|
|
|
return SetCurrentDirectoryW(lpath) == TRUE ? YES : NO;
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#else
|
2005-02-18 06:13:20 +00:00
|
|
|
|
return (chdir(lpath) == 0) ? YES : NO;
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Change the attributes of the file at path to those specified.<br />
|
|
|
|
|
* Returns YES if all requested changes were made (or if the dictionary
|
|
|
|
|
* was nil or empty, so no changes were requested), NO otherwise.<br />
|
2005-11-06 08:43:44 +00:00
|
|
|
|
* On failure, some of the requested changes may have taken place.<br />
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*/
|
|
|
|
|
- (BOOL) changeFileAttributes: (NSDictionary*)attributes atPath: (NSString*)path
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const _CHAR *lpath = 0;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
unsigned long num;
|
|
|
|
|
NSString *str;
|
|
|
|
|
NSDate *date;
|
|
|
|
|
BOOL allOk = YES;
|
|
|
|
|
|
|
|
|
|
if (attributes == nil)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
|
lpath = [defaultManager fileSystemRepresentationWithPath: path];
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#ifndef __MINGW32__
|
2002-09-16 12:43:48 +00:00
|
|
|
|
num = [attributes fileOwnerAccountID];
|
|
|
|
|
if (num != NSNotFound)
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (chown(lpath, num, -1) != 0)
|
2002-09-16 12:43:48 +00:00
|
|
|
|
{
|
|
|
|
|
allOk = NO;
|
|
|
|
|
str = [NSString stringWithFormat:
|
|
|
|
|
@"Unable to change NSFileOwnerAccountID to '%u' - %s",
|
|
|
|
|
num, GSLastErrorStr(errno)];
|
|
|
|
|
ASSIGN(_lastError, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ((str = [attributes fileOwnerAccountName]) != nil)
|
|
|
|
|
{
|
|
|
|
|
BOOL ok = NO;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#ifdef HAVE_PWD_H
|
2005-06-04 18:58:05 +00:00
|
|
|
|
struct passwd *pw;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
|
2005-06-04 18:58:05 +00:00
|
|
|
|
pw = getpwnam([str cStringUsingEncoding: defaultEncoding]);
|
2002-09-16 12:43:48 +00:00
|
|
|
|
if (pw != 0)
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
ok = (chown(lpath, pw->pw_uid, -1) == 0);
|
|
|
|
|
chown(lpath, -1, pw->pw_gid);
|
2002-09-16 12:43:48 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (ok == NO)
|
|
|
|
|
{
|
|
|
|
|
allOk = NO;
|
|
|
|
|
str = [NSString stringWithFormat:
|
|
|
|
|
@"Unable to change NSFileOwnerAccountName to '%@' - %s",
|
|
|
|
|
str, GSLastErrorStr(errno)];
|
|
|
|
|
ASSIGN(_lastError, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
num = [attributes fileGroupOwnerAccountID];
|
|
|
|
|
if (num != NSNotFound)
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (chown(lpath, -1, num) != 0)
|
2002-09-16 12:43:48 +00:00
|
|
|
|
{
|
|
|
|
|
allOk = NO;
|
|
|
|
|
str = [NSString stringWithFormat:
|
|
|
|
|
@"Unable to change NSFileGroupOwnerAccountID to '%u' - %s",
|
|
|
|
|
num, GSLastErrorStr(errno)];
|
|
|
|
|
ASSIGN(_lastError, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ((str = [attributes fileGroupOwnerAccountName]) != nil)
|
|
|
|
|
{
|
|
|
|
|
BOOL ok = NO;
|
|
|
|
|
#ifdef HAVE_GRP_H
|
2005-06-04 18:58:05 +00:00
|
|
|
|
struct group *gp;
|
|
|
|
|
|
|
|
|
|
gp = getgrnam([str cStringUsingEncoding: defaultEncoding]);
|
2002-09-16 12:43:48 +00:00
|
|
|
|
if (gp)
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (chown(lpath, -1, gp->gr_gid) == 0)
|
2002-09-16 12:43:48 +00:00
|
|
|
|
ok = YES;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if (ok == NO)
|
|
|
|
|
{
|
|
|
|
|
allOk = NO;
|
|
|
|
|
str = [NSString stringWithFormat:
|
|
|
|
|
@"Unable to change NSFileGroupOwnerAccountName to '%@' - %s",
|
|
|
|
|
str, GSLastErrorStr(errno)];
|
|
|
|
|
ASSIGN(_lastError, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#endif /* __MINGW32__ */
|
2002-09-16 12:43:48 +00:00
|
|
|
|
|
|
|
|
|
num = [attributes filePosixPermissions];
|
|
|
|
|
if (num != NSNotFound)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_CHMOD(lpath, num) != 0)
|
2002-09-16 12:43:48 +00:00
|
|
|
|
{
|
|
|
|
|
allOk = NO;
|
|
|
|
|
str = [NSString stringWithFormat:
|
|
|
|
|
@"Unable to change NSFilePosixPermissions to '%o' - %s",
|
|
|
|
|
num, GSLastErrorStr(errno)];
|
|
|
|
|
ASSIGN(_lastError, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
date = [attributes fileModificationDate];
|
|
|
|
|
if (date != nil)
|
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
BOOL ok = NO;
|
|
|
|
|
struct _STATB sb;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
#if defined(__WIN32__) || defined(_POSIX_VERSION)
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _UTIMB ub;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#else
|
|
|
|
|
time_t ub[2];
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_STAT(lpath, &sb) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
ok = NO;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#if defined(__WIN32__)
|
|
|
|
|
else if (sb.st_mode & _S_IFDIR)
|
|
|
|
|
{
|
|
|
|
|
ok = YES; // Directories don't have modification times.
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
#if defined(__WIN32__) || defined(_POSIX_VERSION)
|
|
|
|
|
ub.actime = sb.st_atime;
|
|
|
|
|
ub.modtime = [date timeIntervalSince1970];
|
2005-02-18 06:13:20 +00:00
|
|
|
|
ok = (_UTIME(lpath, &ub) == 0);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#else
|
|
|
|
|
ub[0] = sb.st_atime;
|
|
|
|
|
ub[1] = [date timeIntervalSince1970];
|
2005-02-18 06:13:20 +00:00
|
|
|
|
ok = (_UTIME(lpath, ub) == 0);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
if (ok == NO)
|
|
|
|
|
{
|
|
|
|
|
allOk = NO;
|
|
|
|
|
str = [NSString stringWithFormat:
|
|
|
|
|
@"Unable to change NSFileModificationDate to '%@' - %s",
|
|
|
|
|
date, GSLastErrorStr(errno)];
|
|
|
|
|
ASSIGN(_lastError, str);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
return allOk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns an array of path components suitably modified for display
|
|
|
|
|
* to the end user. This modification may render the returned strings
|
|
|
|
|
* unusable for path manipulation, so you should work with two arrays ...
|
2005-11-06 08:43:44 +00:00
|
|
|
|
* one returned by this method (for display to the user), and a
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* parallel one returned by [NSString-pathComponents] (for path
|
|
|
|
|
* manipulation).
|
|
|
|
|
*/
|
|
|
|
|
- (NSArray*) componentsToDisplayForPath: (NSString*)path
|
|
|
|
|
{
|
|
|
|
|
return [path pathComponents];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Reads the file at path an returns its contents as an NSData object.<br />
|
|
|
|
|
* If an error occurs or if path specifies a directory etc then nil is
|
|
|
|
|
* returned.
|
|
|
|
|
*/
|
|
|
|
|
- (NSData*) contentsAtPath: (NSString*)path
|
|
|
|
|
{
|
|
|
|
|
return [NSData dataWithContentsOfFile: path];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns YES if the contents of the file or directory at path1 are the same
|
|
|
|
|
* as those at path2.<br />
|
|
|
|
|
* If path1 and path2 are files, this is a simple comparison. If they are
|
|
|
|
|
* directories, the contents of the files in those subdirectories are
|
|
|
|
|
* compared recursively.<br />
|
|
|
|
|
* Symbolic links are not followed.<br />
|
|
|
|
|
* A comparison checks first file identity, then size, then content.
|
|
|
|
|
*/
|
|
|
|
|
- (BOOL) contentsEqualAtPath: (NSString*)path1 andPath: (NSString*)path2
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *d1;
|
|
|
|
|
NSDictionary *d2;
|
|
|
|
|
NSString *t;
|
|
|
|
|
|
|
|
|
|
if ([path1 isEqual: path2])
|
|
|
|
|
return YES;
|
|
|
|
|
d1 = [self fileAttributesAtPath: path1 traverseLink: NO];
|
|
|
|
|
d2 = [self fileAttributesAtPath: path2 traverseLink: NO];
|
|
|
|
|
t = [d1 fileType];
|
|
|
|
|
if ([t isEqual: [d2 fileType]] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
if ([t isEqual: NSFileTypeRegular])
|
|
|
|
|
{
|
|
|
|
|
if ([d1 fileSize] == [d2 fileSize])
|
|
|
|
|
{
|
|
|
|
|
NSData *c1 = [NSData dataWithContentsOfFile: path1];
|
|
|
|
|
NSData *c2 = [NSData dataWithContentsOfFile: path2];
|
|
|
|
|
|
|
|
|
|
if ([c1 isEqual: c2])
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
else if ([t isEqual: NSFileTypeDirectory])
|
|
|
|
|
{
|
|
|
|
|
NSArray *a1 = [self directoryContentsAtPath: path1];
|
|
|
|
|
NSArray *a2 = [self directoryContentsAtPath: path2];
|
|
|
|
|
unsigned index, count = [a1 count];
|
|
|
|
|
BOOL ok = YES;
|
|
|
|
|
|
|
|
|
|
if ([a1 isEqual: a2] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
for (index = 0; ok == YES && index < count; index++)
|
|
|
|
|
{
|
|
|
|
|
NSString *n = [a1 objectAtIndex: index];
|
|
|
|
|
NSString *p1;
|
|
|
|
|
NSString *p2;
|
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
|
|
|
|
|
|
|
|
|
p1 = [path1 stringByAppendingPathComponent: n];
|
|
|
|
|
p2 = [path2 stringByAppendingPathComponent: n];
|
|
|
|
|
d1 = [self fileAttributesAtPath: p1 traverseLink: NO];
|
|
|
|
|
d2 = [self fileAttributesAtPath: p2 traverseLink: NO];
|
|
|
|
|
t = [d1 fileType];
|
|
|
|
|
if ([t isEqual: [d2 fileType]] == NO)
|
|
|
|
|
{
|
|
|
|
|
ok = NO;
|
|
|
|
|
}
|
|
|
|
|
else if ([t isEqual: NSFileTypeDirectory])
|
|
|
|
|
{
|
|
|
|
|
ok = [self contentsEqualAtPath: p1 andPath: p2];
|
|
|
|
|
}
|
|
|
|
|
RELEASE(pool);
|
|
|
|
|
}
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a new directory, and sets its attributes as specified.<br />
|
|
|
|
|
* Creates other directories in the path as necessary.<br />
|
|
|
|
|
* Returns YES on success, NO on failure.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) createDirectoryAtPath: (NSString*)path
|
|
|
|
|
attributes: (NSDictionary*)attributes
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-18 06:13:20 +00:00
|
|
|
|
NSEnumerator *paths = [[path pathComponents] objectEnumerator];
|
|
|
|
|
NSString *subPath;
|
|
|
|
|
NSString *completePath = nil;
|
2004-03-19 18:34:46 +00:00
|
|
|
|
#else
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const char *lpath;
|
2004-03-19 18:34:46 +00:00
|
|
|
|
char dirpath[PATH_MAX+1];
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _STATB statbuf;
|
2004-03-19 18:34:46 +00:00
|
|
|
|
int len, cur;
|
|
|
|
|
NSDictionary *needChown = nil;
|
|
|
|
|
#endif
|
2000-09-13 03:51:30 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
/* This is consistent with MacOSX - just return NO for an invalid path. */
|
2004-04-25 07:06:41 +00:00
|
|
|
|
if ([path length] == 0)
|
2004-03-19 18:34:46 +00:00
|
|
|
|
return NO;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2000-09-13 03:51:30 +00:00
|
|
|
|
while ((subPath = [paths nextObject]))
|
|
|
|
|
{
|
|
|
|
|
BOOL isDir = NO;
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2000-09-13 03:51:30 +00:00
|
|
|
|
if (completePath == nil)
|
|
|
|
|
completePath = subPath;
|
|
|
|
|
else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
completePath = [completePath stringByAppendingPathComponent: subPath];
|
2000-09-13 03:51:30 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if ([self fileExistsAtPath: completePath isDirectory: &isDir])
|
2000-09-13 03:51:30 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (!isDir)
|
2000-09-13 03:51:30 +00:00
|
|
|
|
NSLog(@"WARNING: during creation of directory %@:"
|
2000-09-13 19:52:42 +00:00
|
|
|
|
@" sub path %@ exists, but is not a directory !",
|
2000-09-13 03:51:30 +00:00
|
|
|
|
path, completePath);
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
else
|
2000-09-13 03:51:30 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const _CHAR *lpath;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-11-28 15:41:35 +00:00
|
|
|
|
lpath = [self fileSystemRepresentationWithPath: completePath];
|
2005-11-05 16:20:19 +00:00
|
|
|
|
if (CreateDirectoryW(lpath, 0) == FALSE)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2000-09-13 03:51:30 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#else
|
2004-03-19 18:34:46 +00:00
|
|
|
|
|
1999-02-20 21:19:15 +00:00
|
|
|
|
/*
|
|
|
|
|
* If there is no file owner specified, and we are running setuid to
|
|
|
|
|
* root, then we assume we need to change ownership to correct user.
|
|
|
|
|
*/
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (attributes == nil || ([attributes fileOwnerAccountID] == NSNotFound
|
2002-09-16 12:43:48 +00:00
|
|
|
|
&& [attributes fileOwnerAccountName] == nil))
|
1999-02-20 21:19:15 +00:00
|
|
|
|
{
|
2002-09-16 12:43:48 +00:00
|
|
|
|
if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
|
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
needChown = [NSDictionary dictionaryWithObjectsAndKeys:
|
2002-09-16 12:43:48 +00:00
|
|
|
|
NSFileOwnerAccountName, NSUserName(), nil];
|
|
|
|
|
}
|
1999-02-20 21:19:15 +00:00
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
lpath = [self fileSystemRepresentationWithPath: path];
|
|
|
|
|
len = strlen(lpath);
|
1999-02-20 21:19:15 +00:00
|
|
|
|
if (len > PATH_MAX) // name too long
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
ASSIGN(_lastError, @"Could not create directory - name too long");
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (strcmp(lpath, "/") == 0 || len == 0) // cannot use "/" or ""
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
1999-09-16 07:21:34 +00:00
|
|
|
|
ASSIGN(_lastError, @"Could not create directory - no name given");
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
strcpy(dirpath, lpath);
|
1999-02-20 21:19:15 +00:00
|
|
|
|
dirpath[len] = '\0';
|
|
|
|
|
if (dirpath[len-1] == '/')
|
|
|
|
|
dirpath[len-1] = '\0';
|
|
|
|
|
cur = 0;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-02-20 21:19:15 +00:00
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
// find next '/'
|
|
|
|
|
while (dirpath[cur] != '/' && cur < len)
|
|
|
|
|
cur++;
|
|
|
|
|
// if first char is '/' then again; (cur == len) -> last component
|
|
|
|
|
if (cur == 0)
|
|
|
|
|
{
|
|
|
|
|
cur++;
|
|
|
|
|
continue;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
1999-02-20 21:19:15 +00:00
|
|
|
|
// check if path from 0 to cur is valid
|
|
|
|
|
dirpath[cur] = '\0';
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_STAT(dirpath, &statbuf) == 0)
|
1999-02-20 21:19:15 +00:00
|
|
|
|
{
|
|
|
|
|
if (cur == len)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2002-04-29 12:20:08 +00:00
|
|
|
|
ASSIGN(_lastError,
|
|
|
|
|
@"Could not create directory - already exists");
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
1999-02-20 21:19:15 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// make new directory
|
|
|
|
|
if (mkdir(dirpath, 0777) != 0)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
|
|
|
|
NSString *s;
|
|
|
|
|
|
|
|
|
|
s = [NSString stringWithFormat: @"Could not create '%s' - '%s'",
|
2001-05-31 22:39:16 +00:00
|
|
|
|
dirpath, GSLastErrorStr(errno)];
|
1999-09-16 07:21:34 +00:00
|
|
|
|
ASSIGN(_lastError, s);
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
1999-02-20 21:19:15 +00:00
|
|
|
|
// if last directory and attributes then change
|
2002-09-16 11:30:22 +00:00
|
|
|
|
if (cur == len && attributes != nil)
|
1999-02-20 21:19:15 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if ([self changeFileAttributes: attributes
|
1999-05-08 05:43:48 +00:00
|
|
|
|
atPath: [self stringWithFileSystemRepresentation: dirpath
|
|
|
|
|
length: cur]] == NO)
|
1999-02-20 21:19:15 +00:00
|
|
|
|
return NO;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
if (needChown != nil)
|
1999-02-20 21:19:15 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if ([self changeFileAttributes: needChown
|
1999-05-08 05:43:48 +00:00
|
|
|
|
atPath: [self stringWithFileSystemRepresentation: dirpath
|
|
|
|
|
length: cur]] == NO)
|
1999-02-20 21:19:15 +00:00
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to change ownership of '%s' to '%@'",
|
|
|
|
|
dirpath, NSUserName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
1999-02-20 21:19:15 +00:00
|
|
|
|
dirpath[cur] = '/';
|
|
|
|
|
cur++;
|
|
|
|
|
}
|
|
|
|
|
while (cur < len);
|
1997-09-13 17:52:31 +00:00
|
|
|
|
|
2000-06-12 05:17:41 +00:00
|
|
|
|
#endif /* !MINGW */
|
2002-09-16 12:43:48 +00:00
|
|
|
|
|
|
|
|
|
// change attributes of last directory
|
|
|
|
|
if ([attributes count] == 0)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
return [self changeFileAttributes: attributes atPath: path];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Creates a new file, and sets its attributes as specified.<br />
|
|
|
|
|
* Initialises the file content with the specified data.<br />
|
|
|
|
|
* Returns YES on success, NO on failure.
|
|
|
|
|
*/
|
|
|
|
|
- (BOOL) createFileAtPath: (NSString*)path
|
|
|
|
|
contents: (NSData*)contents
|
|
|
|
|
attributes: (NSDictionary*)attributes
|
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR *lpath = [self fileSystemRepresentationWithPath: path];
|
2002-09-16 12:43:48 +00:00
|
|
|
|
HANDLE fh;
|
|
|
|
|
DWORD written = 0;
|
|
|
|
|
DWORD len = [contents length];
|
2004-03-19 18:34:46 +00:00
|
|
|
|
#else
|
2005-03-03 17:01:11 +00:00
|
|
|
|
const char *lpath;
|
2004-03-19 18:34:46 +00:00
|
|
|
|
int fd;
|
|
|
|
|
int len;
|
|
|
|
|
int written;
|
|
|
|
|
#endif
|
|
|
|
|
|
2005-11-06 08:43:44 +00:00
|
|
|
|
/* This is consistent with MacOSX - just return NO for an invalid path. */
|
2004-04-25 07:06:41 +00:00
|
|
|
|
if ([path length] == 0)
|
2004-03-19 18:34:46 +00:00
|
|
|
|
return NO;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-11-05 16:20:19 +00:00
|
|
|
|
fh = CreateFileW(lpath, GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
|
2002-09-16 12:43:48 +00:00
|
|
|
|
FILE_ATTRIBUTE_NORMAL, 0);
|
|
|
|
|
if (fh == INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (len > 0)
|
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
WriteFile(fh, [contents bytes], len, &written, 0);
|
2002-09-16 12:43:48 +00:00
|
|
|
|
}
|
|
|
|
|
CloseHandle(fh);
|
|
|
|
|
if (attributes != nil
|
|
|
|
|
&& [self changeFileAttributes: attributes atPath: path] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
#else
|
2005-03-03 17:01:11 +00:00
|
|
|
|
lpath = [self fileSystemRepresentationWithPath: path];
|
2002-09-16 12:43:48 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
fd = open(lpath, GSBINIO|O_WRONLY|O_TRUNC|O_CREAT, 0644);
|
2002-09-16 12:43:48 +00:00
|
|
|
|
if (fd < 0)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
if (attributes != nil
|
|
|
|
|
&& [self changeFileAttributes: attributes atPath: path] == NO)
|
|
|
|
|
{
|
|
|
|
|
close (fd);
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If there is no file owner specified, and we are running setuid to
|
|
|
|
|
* root, then we assume we need to change ownership to correct user.
|
|
|
|
|
*/
|
|
|
|
|
if (attributes == nil || ([attributes fileOwnerAccountID] == NSNotFound
|
|
|
|
|
&& [attributes fileOwnerAccountName] == nil))
|
|
|
|
|
{
|
|
|
|
|
if (geteuid() == 0 && [@"root" isEqualToString: NSUserName()] == NO)
|
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
attributes = [NSDictionary dictionaryWithObjectsAndKeys:
|
2002-09-16 12:43:48 +00:00
|
|
|
|
NSFileOwnerAccountName, NSUserName(), nil];
|
|
|
|
|
if (![self changeFileAttributes: attributes atPath: path])
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to change ownership of '%@' to '%@'",
|
|
|
|
|
path, NSUserName());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
len = [contents length];
|
|
|
|
|
if (len > 0)
|
|
|
|
|
{
|
|
|
|
|
written = write(fd, [contents bytes], len);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
written = 0;
|
|
|
|
|
}
|
|
|
|
|
close (fd);
|
|
|
|
|
#endif
|
|
|
|
|
return written == len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the current working directory used by all instance of the file
|
|
|
|
|
* manager in the current task.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (NSString*) currentDirectoryPath
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
NSString *currentDir = nil;
|
1997-09-13 17:52:31 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-11-05 16:20:19 +00:00
|
|
|
|
int len = GetCurrentDirectoryW(0, 0);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (len > 0)
|
|
|
|
|
{
|
2006-05-24 08:27:39 +00:00
|
|
|
|
_CHAR *lpath = (_CHAR*)objc_calloc(len+10,sizeof(_CHAR));
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-11-05 16:20:19 +00:00
|
|
|
|
if (GetCurrentDirectoryW(len, lpath)>0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
NSString *path;
|
|
|
|
|
|
2005-06-04 07:22:51 +00:00
|
|
|
|
// Windows may count the trailing nul ... we don't want to.
|
|
|
|
|
if (len > 0 && lpath[len] == 0) len--;
|
2005-02-18 06:13:20 +00:00
|
|
|
|
path = [NSString stringWithCharacters: lpath length: len];
|
2005-06-04 07:22:51 +00:00
|
|
|
|
currentDir = path;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2006-05-24 08:27:39 +00:00
|
|
|
|
objc_free(lpath);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#else
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
char path[PATH_MAX];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#ifdef HAVE_GETCWD
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (getcwd(path, PATH_MAX-1) == 0)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return nil;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (getwd(path) == 0)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return nil;
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#endif /* HAVE_GETCWD */
|
2005-02-18 06:13:20 +00:00
|
|
|
|
currentDir = [self stringWithFileSystemRepresentation: path
|
|
|
|
|
length: strlen(path)];
|
2000-06-12 05:17:41 +00:00
|
|
|
|
#endif /* !MINGW */
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
return currentDir;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
2002-09-16 13:23:09 +00:00
|
|
|
|
* Copies the file or directory at source to destination, using a
|
|
|
|
|
* handler object which should respond to
|
|
|
|
|
* [NSObject-fileManager:willProcessPath:] and
|
2004-03-31 14:16:31 +00:00
|
|
|
|
* [NSObject-fileManager:shouldProceedAfterError:] messages.<br />
|
|
|
|
|
* Will not copy to a destination which already exists.
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*/
|
1999-06-18 10:28:11 +00:00
|
|
|
|
- (BOOL) copyPath: (NSString*)source
|
|
|
|
|
toPath: (NSString*)destination
|
2002-09-16 12:43:48 +00:00
|
|
|
|
handler: (id)handler
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2002-03-09 11:46:24 +00:00
|
|
|
|
NSDictionary *attrs;
|
|
|
|
|
NSString *fileType;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
2004-03-31 14:16:31 +00:00
|
|
|
|
if ([self fileExistsAtPath: destination] == YES)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2002-09-16 11:30:22 +00:00
|
|
|
|
attrs = [self fileAttributesAtPath: source traverseLink: NO];
|
2002-03-09 11:46:24 +00:00
|
|
|
|
if (attrs == nil)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2002-09-16 12:43:48 +00:00
|
|
|
|
fileType = [attrs fileType];
|
2002-03-09 11:46:24 +00:00
|
|
|
|
if ([fileType isEqualToString: NSFileTypeDirectory] == YES)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2006-03-08 14:25:55 +00:00
|
|
|
|
NSMutableDictionary *mattrs;
|
|
|
|
|
|
1999-06-18 10:28:11 +00:00
|
|
|
|
/* If destination directory is a descendant of source directory copying
|
|
|
|
|
isn't possible. */
|
|
|
|
|
if ([[destination stringByAppendingString: @"/"]
|
2002-03-09 11:46:24 +00:00
|
|
|
|
hasPrefix: [source stringByAppendingString: @"/"]])
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: destination];
|
2003-02-11 10:26:17 +00:00
|
|
|
|
|
2006-03-08 14:25:55 +00:00
|
|
|
|
/*
|
|
|
|
|
* Don't attempt to retain ownership of copy ... we want the copy
|
|
|
|
|
* to be owned by the current user.
|
|
|
|
|
*/
|
|
|
|
|
mattrs = [attrs mutableCopy];
|
|
|
|
|
[mattrs removeObjectForKey: NSFileOwnerAccountID];
|
|
|
|
|
[mattrs removeObjectForKey: NSFileGroupOwnerAccountID];
|
|
|
|
|
[mattrs removeObjectForKey: NSFileGroupOwnerAccountName];
|
|
|
|
|
[mattrs setObject: NSUserName() forKey: NSFileOwnerAccountName];
|
|
|
|
|
attrs = AUTORELEASE(mattrs);
|
|
|
|
|
|
2002-03-09 11:46:24 +00:00
|
|
|
|
if ([self createDirectoryAtPath: destination attributes: attrs] == NO)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: _lastError
|
|
|
|
|
inPath: destination
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-09 11:46:24 +00:00
|
|
|
|
if ([self _copyPath: source toPath: destination handler: handler] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ([fileType isEqualToString: NSFileTypeSymbolicLink] == YES)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2002-03-09 11:46:24 +00:00
|
|
|
|
NSString *path;
|
|
|
|
|
BOOL result;
|
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: source];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2002-03-09 11:46:24 +00:00
|
|
|
|
path = [self pathContentOfSymbolicLinkAtPath: source];
|
|
|
|
|
result = [self createSymbolicLinkAtPath: destination pathContent: path];
|
|
|
|
|
if (result == NO)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
result = [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot link to file"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2002-03-09 11:46:24 +00:00
|
|
|
|
if (result == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: source];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2002-03-09 11:46:24 +00:00
|
|
|
|
if ([self _copyFile: source toFile: destination handler: handler] == NO)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2002-03-09 11:46:24 +00:00
|
|
|
|
return NO;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2003-04-17 11:23:29 +00:00
|
|
|
|
[self changeFileAttributes: attrs atPath: destination];
|
2002-03-09 11:46:24 +00:00
|
|
|
|
return YES;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
2002-09-16 13:23:09 +00:00
|
|
|
|
* Moves the file or directory at source to destination, using a
|
|
|
|
|
* handler object which should respond to
|
|
|
|
|
* [NSObject-fileManager:willProcessPath:] and
|
|
|
|
|
* [NSObject-fileManager:shouldProceedAfterError:] messages.
|
2004-03-31 14:16:31 +00:00
|
|
|
|
* Will not move to a destination which already exists.<br />
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*/
|
1999-06-18 10:28:11 +00:00
|
|
|
|
- (BOOL) movePath: (NSString*)source
|
2005-02-02 09:43:29 +00:00
|
|
|
|
toPath: (NSString*)destination
|
2002-09-16 12:43:48 +00:00
|
|
|
|
handler: (id)handler
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
BOOL sourceIsDir;
|
|
|
|
|
BOOL fileExists;
|
|
|
|
|
NSString *destinationParent;
|
|
|
|
|
unsigned int sourceDevice;
|
|
|
|
|
unsigned int destinationDevice;
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const _CHAR *sourcePath;
|
|
|
|
|
const _CHAR *destPath;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-11-28 15:41:35 +00:00
|
|
|
|
sourcePath = [self fileSystemRepresentationWithPath: source];
|
|
|
|
|
destPath = [self fileSystemRepresentationWithPath: destination];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
2004-03-31 14:16:31 +00:00
|
|
|
|
if ([self fileExistsAtPath: destination] == YES)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
fileExists = [self fileExistsAtPath: source isDirectory: &sourceIsDir];
|
|
|
|
|
if (!fileExists)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
1999-06-18 10:28:11 +00:00
|
|
|
|
/* Check to see if the source and destination's parent are on the same
|
|
|
|
|
physical device so we can perform a rename syscall directly. */
|
2002-09-16 12:43:48 +00:00
|
|
|
|
sourceDevice = [[self fileSystemAttributesAtPath: source] fileSystemNumber];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
destinationParent = [destination stringByDeletingLastPathComponent];
|
|
|
|
|
if ([destinationParent isEqual: @""])
|
|
|
|
|
destinationParent = @".";
|
|
|
|
|
destinationDevice
|
2002-09-16 12:43:48 +00:00
|
|
|
|
= [[self fileSystemAttributesAtPath: destinationParent] fileSystemNumber];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
|
|
|
|
if (sourceDevice != destinationDevice)
|
|
|
|
|
{
|
|
|
|
|
/* If destination directory is a descendant of source directory moving
|
|
|
|
|
isn't possible. */
|
|
|
|
|
if (sourceIsDir && [[destination stringByAppendingString: @"/"]
|
|
|
|
|
hasPrefix: [source stringByAppendingString: @"/"]])
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
1999-06-18 10:28:11 +00:00
|
|
|
|
if ([self copyPath: source toPath: destination handler: handler])
|
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSDictionary *attributes;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
attributes = [self fileAttributesAtPath: source
|
|
|
|
|
traverseLink: NO];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
[self changeFileAttributes: attributes atPath: destination];
|
|
|
|
|
return [self removeFileAtPath: source handler: handler];
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* source and destination are on the same device so we can simply
|
|
|
|
|
invoke rename on source. */
|
2003-02-11 10:26:17 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: source];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_RENAME (sourcePath, destPath) == -1)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot move file"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return YES;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-06-18 10:28:11 +00:00
|
|
|
|
return NO;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
2003-04-17 11:23:29 +00:00
|
|
|
|
* <p>Links the file or directory at source to destination, using a
|
2002-09-16 13:23:09 +00:00
|
|
|
|
* handler object which should respond to
|
|
|
|
|
* [NSObject-fileManager:willProcessPath:] and
|
|
|
|
|
* [NSObject-fileManager:shouldProceedAfterError:] messages.
|
2003-04-17 11:23:29 +00:00
|
|
|
|
* </p>
|
|
|
|
|
* <p>If the destination is a directory, the source path is linked
|
|
|
|
|
* into that directory, otherwise the destination must not exist,
|
|
|
|
|
* but its parent directory must exist and the source will be linked
|
|
|
|
|
* into the parent as the name specified by the destination.
|
|
|
|
|
* </p>
|
|
|
|
|
* <p>If the source is a symbolic link, it is copied to the destination.<br />
|
|
|
|
|
* If the source is a directory, it is copied to the destination and its
|
|
|
|
|
* contents are linked into the new directory.<br />
|
|
|
|
|
* Otherwise, a hard link is made from the destination to the source.
|
|
|
|
|
* </p>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*/
|
1999-06-18 10:28:11 +00:00
|
|
|
|
- (BOOL) linkPath: (NSString*)source
|
|
|
|
|
toPath: (NSString*)destination
|
2002-09-16 12:43:48 +00:00
|
|
|
|
handler: (id)handler
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2003-04-17 11:23:29 +00:00
|
|
|
|
#ifdef HAVE_LINK
|
|
|
|
|
NSDictionary *attrs;
|
|
|
|
|
NSString *fileType;
|
|
|
|
|
BOOL isDir;
|
|
|
|
|
|
|
|
|
|
if ([self fileExistsAtPath: destination isDirectory: &isDir] == YES
|
|
|
|
|
&& isDir == YES)
|
|
|
|
|
{
|
|
|
|
|
destination = [destination stringByAppendingPathComponent:
|
|
|
|
|
[source lastPathComponent]];
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2003-04-17 11:23:29 +00:00
|
|
|
|
attrs = [self fileAttributesAtPath: source traverseLink: NO];
|
|
|
|
|
if (attrs == nil)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: destination];
|
2003-04-17 11:23:29 +00:00
|
|
|
|
|
|
|
|
|
fileType = [attrs fileType];
|
|
|
|
|
if ([fileType isEqualToString: NSFileTypeDirectory] == YES)
|
|
|
|
|
{
|
|
|
|
|
/* If destination directory is a descendant of source directory linking
|
|
|
|
|
isn't possible because of recursion. */
|
|
|
|
|
if ([[destination stringByAppendingString: @"/"]
|
|
|
|
|
hasPrefix: [source stringByAppendingString: @"/"]])
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([self createDirectoryAtPath: destination attributes: attrs] == NO)
|
|
|
|
|
{
|
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: _lastError
|
|
|
|
|
inPath: destination
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ([self _linkPath: source toPath: destination handler: handler] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ([fileType isEqual: NSFileTypeSymbolicLink])
|
|
|
|
|
{
|
|
|
|
|
NSString *path;
|
|
|
|
|
|
|
|
|
|
path = [self pathContentOfSymbolicLinkAtPath: source];
|
|
|
|
|
if ([self createSymbolicLinkAtPath: destination
|
|
|
|
|
pathContent: path] == NO)
|
|
|
|
|
{
|
|
|
|
|
if ([self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot create symbolic link"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-06-04 18:58:05 +00:00
|
|
|
|
if (link([self fileSystemRepresentationWithPath: source],
|
|
|
|
|
[self fileSystemRepresentationWithPath: destination]) < 0)
|
2003-04-17 11:23:29 +00:00
|
|
|
|
{
|
|
|
|
|
if ([self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot create hard link"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[self changeFileAttributes: attrs atPath: destination];
|
|
|
|
|
return YES;
|
|
|
|
|
#else
|
|
|
|
|
return NO; // Links not supported on this platform
|
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
2002-09-16 13:23:09 +00:00
|
|
|
|
* Removes the file or directory at path, using a
|
|
|
|
|
* handler object which should respond to
|
|
|
|
|
* [NSObject-fileManager:willProcessPath:] and
|
|
|
|
|
* [NSObject-fileManager:shouldProceedAfterError:] messages.
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) removeFileAtPath: (NSString*)path
|
1999-06-18 10:28:11 +00:00
|
|
|
|
handler: handler
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2001-06-15 08:49:03 +00:00
|
|
|
|
BOOL is_dir;
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const _CHAR *lpath;
|
1997-11-03 01:40:03 +00:00
|
|
|
|
|
2001-06-15 09:52:23 +00:00
|
|
|
|
if ([path isEqualToString: @"."] || [path isEqualToString: @".."])
|
|
|
|
|
{
|
|
|
|
|
[NSException raise: NSInvalidArgumentException
|
|
|
|
|
format: @"Attempt to remove illegal path"];
|
|
|
|
|
}
|
1997-11-03 01:40:03 +00:00
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: path];
|
|
|
|
|
|
2005-11-28 15:41:35 +00:00
|
|
|
|
lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
DWORD res;
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
res = GetFileAttributesW(lpath);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (res == WIN32ERR)
|
1997-11-03 01:40:03 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return NO;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (res & FILE_ATTRIBUTE_DIRECTORY)
|
1999-06-22 05:41:09 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
is_dir = YES;
|
2002-09-16 12:43:48 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
else
|
2002-09-16 12:43:48 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
is_dir = NO;
|
|
|
|
|
}
|
|
|
|
|
#else
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _STATB statbuf;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lstat(lpath, &statbuf) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
1999-06-22 05:41:09 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
is_dir = ((statbuf.st_mode & S_IFMT) == S_IFDIR);
|
|
|
|
|
#endif /* MINGW */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!is_dir)
|
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-11-05 16:20:19 +00:00
|
|
|
|
if (DeleteFileW(lpath) == FALSE)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#else
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (unlink(lpath) < 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#endif
|
|
|
|
|
{
|
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: [NSString stringWithCString: GSLastErrorStr (errno)]
|
|
|
|
|
inPath: path];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSArray *contents = [self directoryContentsAtPath: path];
|
|
|
|
|
unsigned count = [contents count];
|
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
NSString *item;
|
|
|
|
|
NSString *next;
|
|
|
|
|
BOOL result;
|
|
|
|
|
CREATE_AUTORELEASE_POOL(arp);
|
|
|
|
|
|
|
|
|
|
item = [contents objectAtIndex: i];
|
|
|
|
|
next = [path stringByAppendingPathComponent: item];
|
|
|
|
|
result = [self removeFileAtPath: next handler: handler];
|
|
|
|
|
RELEASE(arp);
|
|
|
|
|
if (result == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-11-28 15:41:35 +00:00
|
|
|
|
if (_RMDIR([self fileSystemRepresentationWithPath: path]) < 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: [NSString stringWithCString: GSLastErrorStr (errno)]
|
|
|
|
|
inPath: path];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if a file (or directory etc) exists at the specified path.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) fileExistsAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return [self fileExistsAtPath: path isDirectory: 0];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if a file (or directory etc) exists at the specified path.<br />
|
2004-03-31 13:56:49 +00:00
|
|
|
|
* If the isDirectory argument is not a nul pointer, stores a flag
|
|
|
|
|
* in the location it points to, indicating whether the file is a
|
|
|
|
|
* directory or not.<br />
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) fileExistsAtPath: (NSString*)path isDirectory: (BOOL*)isDirectory
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR *lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
if (isDirectory != 0)
|
2004-03-31 13:56:49 +00:00
|
|
|
|
{
|
|
|
|
|
*isDirectory = NO;
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == _NUL)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD res;
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
res = GetFileAttributesW(lpath);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (res == WIN32ERR)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
if (isDirectory != 0)
|
|
|
|
|
{
|
|
|
|
|
if (res & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
|
{
|
|
|
|
|
*isDirectory = YES;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _STATB statbuf;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_STAT(lpath, &statbuf) != 0)
|
2002-02-24 16:45:14 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return NO;
|
2002-02-24 16:45:14 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
if (isDirectory)
|
1999-05-05 18:45:52 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
|
|
|
|
|
{
|
|
|
|
|
*isDirectory = YES;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
}
|
1999-05-05 18:45:52 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2000-06-12 05:17:41 +00:00
|
|
|
|
#endif /* MINGW */
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if a file (or directory etc) exists at the specified path
|
|
|
|
|
* and is readable.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) isReadableFileAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR* lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == _NUL)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
DWORD res;
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
res = GetFileAttributesW(lpath);
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (res == WIN32ERR)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return YES;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (access(lpath, R_OK) == 0)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2002-07-29 19:37:40 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if a file (or directory etc) exists at the specified path
|
|
|
|
|
* and is writable.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) isWritableFileAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR* lpath = [self fileSystemRepresentationWithPath: path];
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == _NUL)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
DWORD res;
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
res = GetFileAttributesW(lpath);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
if (res == WIN32ERR)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (res & FILE_ATTRIBUTE_READONLY)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
return YES;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (access(lpath, W_OK) == 0)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2002-07-29 19:37:40 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if a file (or directory etc) exists at the specified path
|
|
|
|
|
* and is executable (if a directory is executable, you can access its
|
|
|
|
|
* contents).
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) isExecutableFileAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR* lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == _NUL)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
DWORD res;
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
res = GetFileAttributesW(lpath);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
if (res == WIN32ERR)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2006-04-12 19:52:10 +00:00
|
|
|
|
// TODO: Actually should check all extensions in env var PATHEXT
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if ([[[path pathExtension] lowercaseString] isEqualToString: @"exe"])
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2005-11-06 08:43:44 +00:00
|
|
|
|
/* FIXME: On unix, directory accessible == executable, so we simulate that
|
2005-02-02 09:43:29 +00:00
|
|
|
|
here for Windows. Is there a better check for directory access? */
|
|
|
|
|
if (res & FILE_ATTRIBUTE_DIRECTORY)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (access(lpath, X_OK) == 0)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns YES if a file (or directory etc) exists at the specified path
|
|
|
|
|
* and is deletable.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) isDeletableFileAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR* lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == _NUL)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
// TODO - handle directories
|
2005-06-04 07:22:51 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD res;
|
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
res = GetFileAttributesW(lpath);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
if (res == WIN32ERR)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return NO;
|
2002-07-29 19:37:40 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return (res & FILE_ATTRIBUTE_READONLY) ? NO : YES;
|
|
|
|
|
}
|
2000-09-13 03:51:30 +00:00
|
|
|
|
#else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
// TODO - handle directories
|
|
|
|
|
path = [path stringByDeletingLastPathComponent];
|
|
|
|
|
if ([path length] == 0)
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
path = @".";
|
2003-03-23 07:06:27 +00:00
|
|
|
|
}
|
2005-06-04 18:58:05 +00:00
|
|
|
|
lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (access(lpath, X_OK | W_OK) == 0)
|
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2000-09-13 03:51:30 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* If a file (or directory etc) exists at the specified path, and can be
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* queried for its attributes, this method returns a dictionary containing
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* the various attributes of that file. Otherwise nil is returned.<br />
|
|
|
|
|
* If the flag is NO and the file is a symbolic link, the attributes of
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* the link itself (rather than the file it points to) are returned.<br />
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <p>
|
|
|
|
|
* The dictionary keys for attributes are -
|
|
|
|
|
* </p>
|
|
|
|
|
* <deflist>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileAppendOnly</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber ... boolean</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileCreationDate</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSDate when the file was created (if supported)</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileDeviceIdentifier</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber (identifies the device on which the file is stored)</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileExtensionHidden</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber ... boolean</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileGroupOwnerAccountName</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSString name of the file group</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileGroupOwnerAccountID</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber ID of the file group</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileHFSCreatorCode</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber not used</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileHFSTypeCode</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber not used</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileImmutable</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber ... boolean</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileModificationDate</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSDate when the file was last modified</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileOwnerAccountName</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSString name of the file owner</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileOwnerAccountID</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber ID of the file owner</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFilePosixPermissions</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber posix access permissions mask</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileReferenceCount</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber number of links to this file</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSize</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber size of the file in bytes</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemFileNumber</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the identifier for the file on the filesystem</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemNumber</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the filesystem on which the file is stored</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileType</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSString the type of file</desc>
|
|
|
|
|
* </deflist>
|
|
|
|
|
* <p>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* The [NSDictionary] class also has a set of convenience accessor methods
|
|
|
|
|
* which enable you to get at file attribute information more efficiently
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* than using the keys above to extract it. You should generally
|
|
|
|
|
* use the accessor methods where they are available.
|
|
|
|
|
* </p>
|
|
|
|
|
* <list>
|
|
|
|
|
* <item>[NSDictionary-fileCreationDate]</item>
|
|
|
|
|
* <item>[NSDictionary-fileExtensionHidden]</item>
|
|
|
|
|
* <item>[NSDictionary-fileHFSCreatorCode]</item>
|
|
|
|
|
* <item>[NSDictionary-fileHFSTypeCode]</item>
|
|
|
|
|
* <item>[NSDictionary-fileIsAppendOnly]</item>
|
|
|
|
|
* <item>[NSDictionary-fileIsImmutable]</item>
|
|
|
|
|
* <item>[NSDictionary-fileSize]</item>
|
|
|
|
|
* <item>[NSDictionary-fileType]</item>
|
|
|
|
|
* <item>[NSDictionary-fileOwnerAccountName]</item>
|
|
|
|
|
* <item>[NSDictionary-fileOwnerAccountID]</item>
|
|
|
|
|
* <item>[NSDictionary-fileGroupOwnerAccountName]</item>
|
|
|
|
|
* <item>[NSDictionary-fileGroupOwnerAccountID]</item>
|
|
|
|
|
* <item>[NSDictionary-fileModificationDate]</item>
|
|
|
|
|
* <item>[NSDictionary-filePosixPermissions]</item>
|
|
|
|
|
* <item>[NSDictionary-fileSystemNumber]</item>
|
|
|
|
|
* <item>[NSDictionary-fileSystemFileNumber]</item>
|
|
|
|
|
* </list>
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (NSDictionary*) fileAttributesAtPath: (NSString*)path traverseLink: (BOOL)flag
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
NSDictionary *d;
|
|
|
|
|
|
2005-06-04 18:58:05 +00:00
|
|
|
|
d = [GSAttrDictionary attributesAt:
|
2005-11-28 15:41:35 +00:00
|
|
|
|
[self fileSystemRepresentationWithPath: path] traverseLink: flag];
|
2002-09-16 11:30:22 +00:00
|
|
|
|
return d;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a dictionary containing the filesystem attributes for the
|
|
|
|
|
* specified path (or nil if the path is not valid).<br />
|
|
|
|
|
* <deflist>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemSize</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the size of the filesystem in bytes</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemFreeSize</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the amount of unused space on the filesystem in bytes</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemNodes</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the number of nodes in use to store files</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemFreeNodes</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the number of nodes available to create files</desc>
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <term><code>NSFileSystemNumber</code></term>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* <desc>NSNumber the identifying number for the filesystem</desc>
|
|
|
|
|
* </deflist>
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (NSDictionary*) fileSystemAttributesAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2001-04-10 03:27:01 +00:00
|
|
|
|
unsigned long long totalsize, freesize;
|
1999-06-22 05:41:09 +00:00
|
|
|
|
id values[5];
|
|
|
|
|
id keys[5] = {
|
2005-02-02 09:43:29 +00:00
|
|
|
|
NSFileSystemSize,
|
|
|
|
|
NSFileSystemFreeSize,
|
|
|
|
|
NSFileSystemNodes,
|
|
|
|
|
NSFileSystemFreeNodes,
|
|
|
|
|
NSFileSystemNumber
|
|
|
|
|
};
|
1999-06-22 05:41:09 +00:00
|
|
|
|
DWORD SectorsPerCluster, BytesPerSector, NumberFreeClusters;
|
|
|
|
|
DWORD TotalNumberClusters;
|
2005-11-28 15:41:35 +00:00
|
|
|
|
const _CHAR *lpath = [self fileSystemRepresentationWithPath: path];
|
1999-06-22 05:41:09 +00:00
|
|
|
|
|
2005-11-05 16:20:19 +00:00
|
|
|
|
if (!GetDiskFreeSpaceW(lpath, &SectorsPerCluster,
|
1999-06-22 05:41:09 +00:00
|
|
|
|
&BytesPerSector, &NumberFreeClusters, &TotalNumberClusters))
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1999-06-22 05:41:09 +00:00
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
totalsize = (unsigned long long)TotalNumberClusters
|
|
|
|
|
* (unsigned long long)SectorsPerCluster
|
|
|
|
|
* (unsigned long long)BytesPerSector;
|
|
|
|
|
freesize = (unsigned long long)NumberFreeClusters
|
|
|
|
|
* (unsigned long long)SectorsPerCluster
|
|
|
|
|
* (unsigned long long)BytesPerSector;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
values[0] = [NSNumber numberWithUnsignedLongLong: totalsize];
|
|
|
|
|
values[1] = [NSNumber numberWithUnsignedLongLong: freesize];
|
1999-06-22 05:41:09 +00:00
|
|
|
|
values[2] = [NSNumber numberWithLong: LONG_MAX];
|
|
|
|
|
values[3] = [NSNumber numberWithLong: LONG_MAX];
|
|
|
|
|
values[4] = [NSNumber numberWithUnsignedInt: 0];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-06-22 05:41:09 +00:00
|
|
|
|
return [NSDictionary dictionaryWithObjects: values forKeys: keys count: 5];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#else
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#if defined(HAVE_SYS_VFS_H) || defined(HAVE_SYS_STATFS_H) \
|
|
|
|
|
|| defined(HAVE_SYS_MOUNT_H)
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _STATB statbuf;
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_STATVFS
|
1999-06-22 05:41:09 +00:00
|
|
|
|
struct statvfs statfsbuf;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#else
|
1999-06-22 05:41:09 +00:00
|
|
|
|
struct statfs statfsbuf;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#endif
|
2001-04-10 03:27:01 +00:00
|
|
|
|
unsigned long long totalsize, freesize;
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const char* lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-06-22 05:41:09 +00:00
|
|
|
|
id values[5];
|
|
|
|
|
id keys[5] = {
|
2002-10-14 08:52:39 +00:00
|
|
|
|
NSFileSystemSize,
|
|
|
|
|
NSFileSystemFreeSize,
|
|
|
|
|
NSFileSystemNodes,
|
|
|
|
|
NSFileSystemFreeNodes,
|
|
|
|
|
NSFileSystemNumber
|
|
|
|
|
};
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_STAT(lpath, &statbuf) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_STATVFS
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (statvfs(lpath, &statfsbuf) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#else
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (statfs(lpath, &statfsbuf) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
totalsize = (unsigned long long) statfsbuf.f_bsize
|
|
|
|
|
* (unsigned long long) statfsbuf.f_blocks;
|
|
|
|
|
freesize = (unsigned long long) statfsbuf.f_bsize
|
|
|
|
|
* (unsigned long long) statfsbuf.f_bavail;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
values[0] = [NSNumber numberWithUnsignedLongLong: totalsize];
|
|
|
|
|
values[1] = [NSNumber numberWithUnsignedLongLong: freesize];
|
1999-06-22 05:41:09 +00:00
|
|
|
|
values[2] = [NSNumber numberWithLong: statfsbuf.f_files];
|
|
|
|
|
values[3] = [NSNumber numberWithLong: statfsbuf.f_ffree];
|
|
|
|
|
values[4] = [NSNumber numberWithUnsignedLong: statbuf.st_dev];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-06-22 05:41:09 +00:00
|
|
|
|
return [NSDictionary dictionaryWithObjects: values forKeys: keys count: 5];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#else
|
1999-06-22 05:41:09 +00:00
|
|
|
|
return nil;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
#endif
|
2000-06-12 05:17:41 +00:00
|
|
|
|
#endif /* MINGW */
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-15 07:51:29 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an array of the contents of the specified directory.<br />
|
|
|
|
|
* The listing does <strong>not</strong> recursively list subdirectories.<br />
|
|
|
|
|
* The special files '.' and '..' are not listed.<br />
|
2002-10-14 08:52:39 +00:00
|
|
|
|
* Indicates an error by returning nil (eg. if path is not a directory or
|
|
|
|
|
* it can't be read for some reason).
|
2002-09-15 07:51:29 +00:00
|
|
|
|
*/
|
1999-02-21 20:01:41 +00:00
|
|
|
|
- (NSArray*) directoryContentsAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
1999-05-08 05:43:48 +00:00
|
|
|
|
NSDirectoryEnumerator *direnum;
|
|
|
|
|
NSMutableArray *content;
|
|
|
|
|
IMP nxtImp;
|
|
|
|
|
IMP addImp;
|
2000-09-22 04:20:52 +00:00
|
|
|
|
BOOL is_dir;
|
2000-05-24 09:08:32 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* See if this is a directory (don't follow links).
|
|
|
|
|
*/
|
2000-09-22 04:20:52 +00:00
|
|
|
|
if ([self fileExistsAtPath: path isDirectory: &is_dir] == NO || is_dir == NO)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
/* We initialize the directory enumerator with justContents == YES,
|
|
|
|
|
which tells the NSDirectoryEnumerator code that we only enumerate
|
|
|
|
|
the contents non-recursively once, and exit. NSDirectoryEnumerator
|
2005-11-06 08:43:44 +00:00
|
|
|
|
can perform some optimisations using this assumption. */
|
2005-02-02 09:43:29 +00:00
|
|
|
|
direnum = [[NSDirectoryEnumerator alloc] initWithDirectoryPath: path
|
2005-06-04 07:22:51 +00:00
|
|
|
|
recurseIntoSubdirectories: NO
|
|
|
|
|
followSymlinks: NO
|
|
|
|
|
justContents: YES
|
|
|
|
|
for: self];
|
1999-02-21 20:01:41 +00:00
|
|
|
|
content = [NSMutableArray arrayWithCapacity: 128];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
|
|
|
|
nxtImp = [direnum methodForSelector: @selector(nextObject)];
|
2000-01-09 15:30:11 +00:00
|
|
|
|
addImp = [content methodForSelector: @selector(addObject:)];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
|
|
|
|
while ((path = (*nxtImp)(direnum, @selector(nextObject))) != nil)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
|
|
|
|
(*addImp)(content, @selector(addObject:), path);
|
|
|
|
|
}
|
1999-02-21 20:01:41 +00:00
|
|
|
|
RELEASE(direnum);
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2002-10-14 08:52:39 +00:00
|
|
|
|
return [content makeImmutableCopyOnFail: NO];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-15 07:51:29 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the name of the file or directory at path. Converts it into
|
|
|
|
|
* a format for display to an end user. This may render it unusable as
|
|
|
|
|
* part of a file/path name.<br />
|
|
|
|
|
* For instance, if a user has elected not to see file extensions, this
|
|
|
|
|
* method may return filenames with the extension removed.<br />
|
|
|
|
|
* The default operation is to return the result of calling
|
|
|
|
|
* [NSString-lastPathComponent] on the path.
|
|
|
|
|
*/
|
|
|
|
|
- (NSString*) displayNameAtPath: (NSString*)path
|
|
|
|
|
{
|
|
|
|
|
return [path lastPathComponent];
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an enumerator which can be used to return each item with
|
|
|
|
|
* the directory at path in turn.<br />
|
|
|
|
|
* The enumeration is recursive ... following all nested subdirectories.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (NSDirectoryEnumerator*) enumeratorAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
1999-06-22 05:41:09 +00:00
|
|
|
|
return AUTORELEASE([[NSDirectoryEnumerator alloc]
|
2005-02-02 09:43:29 +00:00
|
|
|
|
initWithDirectoryPath: path
|
2001-04-19 22:09:25 +00:00
|
|
|
|
recurseIntoSubdirectories: YES
|
|
|
|
|
followSymlinks: NO
|
2005-06-04 07:22:51 +00:00
|
|
|
|
justContents: NO
|
|
|
|
|
for: self]);
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns an array containing the (relative) paths of all the items
|
|
|
|
|
* in the directory at path.<br />
|
|
|
|
|
* The listing follows all subdirectories, so it can produce a very
|
|
|
|
|
* large array ... use with care.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (NSArray*) subpathsAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
1999-05-08 05:43:48 +00:00
|
|
|
|
NSDirectoryEnumerator *direnum;
|
|
|
|
|
NSMutableArray *content;
|
|
|
|
|
BOOL isDir;
|
|
|
|
|
IMP nxtImp;
|
|
|
|
|
IMP addImp;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
if (![self fileExistsAtPath: path isDirectory: &isDir] || !isDir)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
direnum = [[NSDirectoryEnumerator alloc] initWithDirectoryPath: path
|
2005-06-04 07:22:51 +00:00
|
|
|
|
recurseIntoSubdirectories: YES
|
|
|
|
|
followSymlinks: NO
|
|
|
|
|
justContents: NO
|
|
|
|
|
for: self];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
content = [NSMutableArray arrayWithCapacity: 128];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
nxtImp = [direnum methodForSelector: @selector(nextObject)];
|
2000-01-09 15:30:11 +00:00
|
|
|
|
addImp = [content methodForSelector: @selector(addObject:)];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
while ((path = (*nxtImp)(direnum, @selector(nextObject))) != nil)
|
2001-04-19 22:09:25 +00:00
|
|
|
|
{
|
|
|
|
|
(*addImp)(content, @selector(addObject:), path);
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
RELEASE(direnum);
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2002-10-14 08:52:39 +00:00
|
|
|
|
return [content makeImmutableCopyOnFail: NO];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Creates a symbolic link at path which links to the location
|
|
|
|
|
* specified by otherPath.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) createSymbolicLinkAtPath: (NSString*)path
|
1999-06-22 05:41:09 +00:00
|
|
|
|
pathContent: (NSString*)otherPath
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_SYMLINK
|
2001-06-13 15:30:38 +00:00
|
|
|
|
const char* newpath = [self fileSystemRepresentationWithPath: path];
|
|
|
|
|
const char* oldpath = [self fileSystemRepresentationWithPath: otherPath];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2001-06-13 15:30:38 +00:00
|
|
|
|
return (symlink(oldpath, newpath) == 0);
|
2000-09-13 03:51:30 +00:00
|
|
|
|
#else
|
|
|
|
|
return NO;
|
1997-09-13 17:52:31 +00:00
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns the name of the file or directory that the symbolic link
|
|
|
|
|
* at path points to.
|
|
|
|
|
*/
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (NSString*) pathContentOfSymbolicLinkAtPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2002-05-02 21:22:06 +00:00
|
|
|
|
#ifdef HAVE_READLINK
|
2005-02-18 06:17:37 +00:00
|
|
|
|
char buf[PATH_MAX];
|
2005-02-18 06:13:20 +00:00
|
|
|
|
const char* lpath = [self fileSystemRepresentationWithPath: path];
|
2005-02-18 06:17:37 +00:00
|
|
|
|
int llen = readlink(lpath, buf, PATH_MAX-1);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
if (llen > 0)
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
2005-02-18 06:17:37 +00:00
|
|
|
|
return [self stringWithFileSystemRepresentation: buf length: llen];
|
2002-07-29 19:37:40 +00:00
|
|
|
|
}
|
1999-05-08 05:43:48 +00:00
|
|
|
|
else
|
2002-07-29 19:37:40 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2000-09-13 03:51:30 +00:00
|
|
|
|
#else
|
|
|
|
|
return nil;
|
|
|
|
|
#endif
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-11-28 15:41:35 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
|
|
|
|
- (const GSNativeChar*) fileSystemRepresentationWithPath: (NSString*)path
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
return
|
|
|
|
|
(const GSNativeChar*)[path cStringUsingEncoding: NSUnicodeStringEncoding];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
|
- (NSString*) stringWithFileSystemRepresentation: (const GSNativeChar*)string
|
1999-06-22 05:41:09 +00:00
|
|
|
|
length: (unsigned int)len
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-11-05 16:20:19 +00:00
|
|
|
|
return [NSString stringWithCharacters: string length: len];
|
2005-11-05 07:12:00 +00:00
|
|
|
|
}
|
2005-06-04 07:22:51 +00:00
|
|
|
|
#else
|
2005-11-28 15:41:35 +00:00
|
|
|
|
- (const GSNativeChar*) fileSystemRepresentationWithPath: (NSString*)path
|
2005-11-05 07:12:00 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
return
|
|
|
|
|
(const GSNativeChar*)[path cStringUsingEncoding: defaultEncoding];
|
2005-11-05 07:12:00 +00:00
|
|
|
|
}
|
2005-11-28 15:41:35 +00:00
|
|
|
|
- (NSString*) stringWithFileSystemRepresentation: (const GSNativeChar*)string
|
2005-11-05 07:12:00 +00:00
|
|
|
|
length: (unsigned int)len
|
|
|
|
|
{
|
2005-06-04 18:58:05 +00:00
|
|
|
|
return AUTORELEASE([[NSString allocWithZone: NSDefaultMallocZone()]
|
|
|
|
|
initWithBytes: string length: len encoding: defaultEncoding]);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2005-11-05 07:12:00 +00:00
|
|
|
|
#endif
|
2002-04-28 15:33:30 +00:00
|
|
|
|
|
1997-03-03 20:10:10 +00:00
|
|
|
|
@end /* NSFileManager */
|
|
|
|
|
|
2002-01-01 14:24:45 +00:00
|
|
|
|
/* A directory to enumerate. We keep a stack of the directories we
|
|
|
|
|
still have to enumerate. We start by putting the top-level
|
|
|
|
|
directory into the stack, then we start reading files from it
|
|
|
|
|
(using readdir). If we find a file which is actually a directory,
|
|
|
|
|
and if we have to recurse into it, we create a new
|
|
|
|
|
GSEnumeratedDirectory struct for the subdirectory, open its DIR
|
|
|
|
|
*pointer for reading, and put it on top of the stack, so next time
|
|
|
|
|
-nextObject is called, it will read from that directory instead of
|
|
|
|
|
the top level one. Once all the subdirectory is read, it is
|
|
|
|
|
removed from the stack, so the top of the stack if the top
|
|
|
|
|
directory again, and enumeration continues in there. */
|
2001-04-19 22:09:25 +00:00
|
|
|
|
typedef struct _GSEnumeratedDirectory {
|
2005-02-18 06:13:20 +00:00
|
|
|
|
NSString *path;
|
|
|
|
|
_DIR *pointer;
|
2001-04-19 22:09:25 +00:00
|
|
|
|
} GSEnumeratedDirectory;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
|
|
|
|
|
2001-04-19 22:09:25 +00:00
|
|
|
|
inline void gsedRelease(GSEnumeratedDirectory X)
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
DESTROY(X.path);
|
2005-02-18 06:13:20 +00:00
|
|
|
|
_CLOSEDIR(X.pointer);
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-31 07:24:27 +00:00
|
|
|
|
#define GSI_ARRAY_TYPES 0
|
|
|
|
|
#define GSI_ARRAY_TYPE GSEnumeratedDirectory
|
2002-01-31 07:20:16 +00:00
|
|
|
|
#define GSI_ARRAY_RELEASE(A, X) gsedRelease(X.ext)
|
|
|
|
|
#define GSI_ARRAY_RETAIN(A, X)
|
2001-04-19 22:09:25 +00:00
|
|
|
|
|
2003-07-31 23:49:32 +00:00
|
|
|
|
#include "GNUstepBase/GSIArray.h"
|
2001-04-19 22:09:25 +00:00
|
|
|
|
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <p>This is a subclass of <code>NSEnumerator</code> which provides a full
|
|
|
|
|
* listing of all the files beneath a directory and its subdirectories.
|
|
|
|
|
* Instances can be obtained through [NSFileManager-enumeratorAtPath:],
|
|
|
|
|
* or through an initializer in this class. (For compatibility with OS X,
|
|
|
|
|
* use the <code>NSFileManager</code> method.)</p>
|
2002-09-16 12:43:48 +00:00
|
|
|
|
*
|
2004-06-22 22:40:40 +00:00
|
|
|
|
* <p>This implementation is optimized and performance should be comparable
|
|
|
|
|
* to the speed of standard Unix tools for large directories.</p>
|
|
|
|
|
*/
|
|
|
|
|
@implementation NSDirectoryEnumerator
|
|
|
|
|
/*
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* The Objective-C interface hides a traditional C implementation.
|
|
|
|
|
* This was the only way I could get near the speed of standard unix
|
|
|
|
|
* tools for big directories.
|
|
|
|
|
*/
|
|
|
|
|
|
2001-04-19 22:09:25 +00:00
|
|
|
|
+ (void) initialize
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2001-04-19 22:09:25 +00:00
|
|
|
|
if (self == [NSDirectoryEnumerator class])
|
1999-02-21 20:01:41 +00:00
|
|
|
|
{
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initializing
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Initialize instance to enumerate contents at path, which should be a
|
|
|
|
|
* directory and can be specified in relative or absolute, and may include
|
|
|
|
|
* Unix conventions like '<code>~</code>' for user home directory, which will
|
|
|
|
|
* be appropriately converted on Windoze systems. The justContents flag, if
|
|
|
|
|
* set, is equivalent to recurseIntoSubdirectories = NO and followSymlinks =
|
|
|
|
|
* NO, but the implementation will be made more efficient.
|
|
|
|
|
*/
|
2005-02-02 09:43:29 +00:00
|
|
|
|
- (id) initWithDirectoryPath: (NSString*)path
|
1999-06-17 19:09:25 +00:00
|
|
|
|
recurseIntoSubdirectories: (BOOL)recurse
|
|
|
|
|
followSymlinks: (BOOL)follow
|
2001-04-19 22:09:25 +00:00
|
|
|
|
justContents: (BOOL)justContents
|
2005-06-04 07:22:51 +00:00
|
|
|
|
for: (NSFileManager*)mgr
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2004-06-22 22:40:40 +00:00
|
|
|
|
//TODO: the justContents flag is currently basically useless and should be
|
|
|
|
|
// removed
|
2005-02-18 06:13:20 +00:00
|
|
|
|
_DIR *dir_pointer;
|
|
|
|
|
const _CHAR *localPath;
|
|
|
|
|
|
* Add support for systems that support unichar file paths (e.g.
Windows).
* Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:,
_openStepPathFromLocal:): New methods.
(NSDirectoryEnumerator): Updated ivars.
* Source/NSFileManager.m: Idem.
(-changeCurrentDirectoryPath, changeFileAttributes:,
currentDirectoryPath, etc): Update for Windows unichar paths.
* Headers/Foundation/NSString.h: (-unicharString,
-localFromOpenStepPath:, _openStepPathFromLocal:): New methods.
* Source/NSString.m: Idem.
* Source/GSFileHandle.m (-initForReadingAtPath:,
-initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows
unichar paths.
* Source/NSData.m (readContentsOfFile, -writeToFile:,
initWithContentsOfMappedFile:): Idem.
* Source/NSTask.m (NSConcreteWindowsTask): Update for Windows
unichar paths.
(Patch from Roland Schwingle <roland.schwingel@onevision.de>)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
2004-12-29 04:21:37 +00:00
|
|
|
|
self = [super init];
|
|
|
|
|
|
2005-06-04 07:22:51 +00:00
|
|
|
|
_mgr = RETAIN(mgr);
|
2001-04-19 22:09:25 +00:00
|
|
|
|
_stack = NSZoneMalloc([self zone], sizeof(GSIArray_t));
|
|
|
|
|
GSIArrayInitWithZoneAndCapacity(_stack, [self zone], 64);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-09-16 07:21:34 +00:00
|
|
|
|
_flags.isRecursive = recurse;
|
|
|
|
|
_flags.isFollowing = follow;
|
2001-04-19 22:09:25 +00:00
|
|
|
|
_flags.justContents = justContents;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
_topPath = [[NSString alloc] initWithString: path];
|
|
|
|
|
|
2005-11-28 15:41:35 +00:00
|
|
|
|
localPath = [_mgr fileSystemRepresentationWithPath: path];
|
2005-02-18 06:13:20 +00:00
|
|
|
|
dir_pointer = _OPENDIR(localPath);
|
2001-04-19 22:09:25 +00:00
|
|
|
|
if (dir_pointer)
|
|
|
|
|
{
|
|
|
|
|
GSIArrayItem item;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
item.ext.path = @"";
|
2001-04-19 22:09:25 +00:00
|
|
|
|
item.ext.pointer = dir_pointer;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2001-04-19 22:09:25 +00:00
|
|
|
|
GSIArrayAddItem(_stack, item);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
NSLog(@"Failed to recurse into directory '%@' - %s", path,
|
2005-02-18 06:13:20 +00:00
|
|
|
|
GSLastErrorStr(errno));
|
2001-04-19 22:09:25 +00:00
|
|
|
|
}
|
1999-02-21 20:01:41 +00:00
|
|
|
|
return self;
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-02-21 20:01:41 +00:00
|
|
|
|
- (void) dealloc
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2001-04-19 22:09:25 +00:00
|
|
|
|
GSIArrayEmpty(_stack);
|
|
|
|
|
NSZoneFree([self zone], _stack);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
DESTROY(_topPath);
|
|
|
|
|
DESTROY(_currentFilePath);
|
2005-06-04 07:22:51 +00:00
|
|
|
|
DESTROY(_mgr);
|
1999-01-20 13:28:28 +00:00
|
|
|
|
[super dealloc];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a dictionary containing the attributes of the directory
|
|
|
|
|
* at which enumeration started. <br />
|
|
|
|
|
* The contents of this dictionary are as produced by
|
|
|
|
|
* [NSFileManager-fileAttributesAtPath:traverseLink:]
|
|
|
|
|
*/
|
1999-02-21 20:01:41 +00:00
|
|
|
|
- (NSDictionary*) directoryAttributes
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return [_mgr fileAttributesAtPath: _topPath
|
|
|
|
|
traverseLink: _flags.isFollowing];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns a dictionary containing the attributes of the file
|
|
|
|
|
* currently being enumerated. <br />
|
|
|
|
|
* The contents of this dictionary are as produced by
|
|
|
|
|
* [NSFileManager-fileAttributesAtPath:traverseLink:]
|
|
|
|
|
*/
|
1999-02-21 20:01:41 +00:00
|
|
|
|
- (NSDictionary*) fileAttributes
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
|
return [_mgr fileAttributesAtPath: _currentFilePath
|
|
|
|
|
traverseLink: _flags.isFollowing];
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
/**
|
|
|
|
|
* Informs the receiver that any descendents of the current directory
|
2005-11-06 13:53:40 +00:00
|
|
|
|
* should be skipped rather than enumerated. Use this to avoid enumerating
|
2002-09-16 12:43:48 +00:00
|
|
|
|
* the contents of directories you are not interested in.
|
|
|
|
|
*/
|
1999-02-21 20:01:41 +00:00
|
|
|
|
- (void) skipDescendents
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (GSIArrayCount(_stack) > 0)
|
|
|
|
|
{
|
|
|
|
|
GSIArrayRemoveLastItem(_stack);
|
|
|
|
|
if (_currentFilePath != 0)
|
2001-04-19 22:09:25 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
DESTROY(_currentFilePath);
|
|
|
|
|
}
|
2001-04-19 22:09:25 +00:00
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
/*
|
|
|
|
|
* finds the next file according to the top enumerator
|
|
|
|
|
* - if there is a next file it is put in currentFile
|
|
|
|
|
* - if the current file is a directory and if isRecursive calls
|
|
|
|
|
* recurseIntoDirectory: currentFile
|
|
|
|
|
* - if the current file is a symlink to a directory and if isRecursive
|
|
|
|
|
* and isFollowing calls recurseIntoDirectory: currentFile
|
|
|
|
|
* - if at end of current directory pops stack and attempts to
|
|
|
|
|
* find the next entry in the parent
|
|
|
|
|
* - sets currentFile to nil if there are no more files to enumerate
|
|
|
|
|
*/
|
1999-06-17 19:09:25 +00:00
|
|
|
|
- (id) nextObject
|
1997-03-03 20:10:10 +00:00
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
NSString *returnFileName = 0;
|
|
|
|
|
|
|
|
|
|
if (_currentFilePath != 0)
|
|
|
|
|
{
|
|
|
|
|
DESTROY(_currentFilePath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (GSIArrayCount(_stack) > 0)
|
|
|
|
|
{
|
|
|
|
|
GSEnumeratedDirectory dir = GSIArrayLastItem(_stack).ext;
|
2005-02-18 06:13:20 +00:00
|
|
|
|
struct _DIRENT *dirbuf;
|
|
|
|
|
struct _STATB statbuf;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
dirbuf = _READDIR(dir.pointer);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
|
|
|
|
if (dirbuf)
|
|
|
|
|
{
|
2005-11-05 16:20:19 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
/* Skip "." and ".." directory entries */
|
|
|
|
|
if (wcscmp(dirbuf->d_name, L".") == 0
|
|
|
|
|
|| wcscmp(dirbuf->d_name, L"..") == 0)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Name of file to return */
|
2005-06-04 07:22:51 +00:00
|
|
|
|
returnFileName = [_mgr
|
2005-11-05 16:20:19 +00:00
|
|
|
|
stringWithFileSystemRepresentation: dirbuf->d_name
|
|
|
|
|
length: wcslen(dirbuf->d_name)];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#else
|
|
|
|
|
/* Skip "." and ".." directory entries */
|
|
|
|
|
if (strcmp(dirbuf->d_name, ".") == 0
|
|
|
|
|
|| strcmp(dirbuf->d_name, "..") == 0)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* Name of file to return */
|
2005-06-04 07:22:51 +00:00
|
|
|
|
returnFileName = [_mgr
|
|
|
|
|
stringWithFileSystemRepresentation: dirbuf->d_name
|
|
|
|
|
length: strlen(dirbuf->d_name)];
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#endif
|
|
|
|
|
returnFileName = [dir.path stringByAppendingPathComponent:
|
|
|
|
|
returnFileName];
|
|
|
|
|
RETAIN(returnFileName);
|
|
|
|
|
|
|
|
|
|
/* TODO - can this one can be removed ? */
|
|
|
|
|
if (!_flags.justContents)
|
|
|
|
|
_currentFilePath = RETAIN([_topPath stringByAppendingPathComponent:
|
|
|
|
|
returnFileName]);
|
|
|
|
|
|
|
|
|
|
if (_flags.isRecursive == YES)
|
|
|
|
|
{
|
|
|
|
|
// Do not follow links
|
|
|
|
|
#ifdef S_IFLNK
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#ifdef __MINGW32__
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#warning "lstat does not support unichars"
|
|
|
|
|
#else
|
|
|
|
|
if (!_flags.isFollowing)
|
|
|
|
|
{
|
2005-06-04 18:58:05 +00:00
|
|
|
|
if (lstat([_mgr fileSystemRepresentationWithPath:
|
|
|
|
|
_currentFilePath], &statbuf) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// If link then return it as link
|
|
|
|
|
if (S_IFLNK == (S_IFMT & statbuf.st_mode))
|
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2001-04-19 22:09:25 +00:00
|
|
|
|
{
|
2005-11-28 15:41:35 +00:00
|
|
|
|
if (_STAT([_mgr fileSystemRepresentationWithPath:
|
2005-06-04 18:58:05 +00:00
|
|
|
|
_currentFilePath], &statbuf) != 0)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
break;
|
|
|
|
|
}
|
2001-04-19 22:09:25 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (S_IFDIR == (S_IFMT & statbuf.st_mode))
|
2001-04-19 22:09:25 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
_DIR* dir_pointer;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
dir_pointer
|
2005-11-28 15:41:35 +00:00
|
|
|
|
= _OPENDIR([_mgr fileSystemRepresentationWithPath:
|
2005-06-04 18:58:05 +00:00
|
|
|
|
_currentFilePath]);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (dir_pointer)
|
|
|
|
|
{
|
|
|
|
|
GSIArrayItem item;
|
|
|
|
|
|
|
|
|
|
item.ext.path = RETAIN(returnFileName);
|
|
|
|
|
item.ext.pointer = dir_pointer;
|
|
|
|
|
|
|
|
|
|
GSIArrayAddItem(_stack, item);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Failed to recurse into directory '%@' - %s",
|
|
|
|
|
_currentFilePath, GSLastErrorStr(errno));
|
|
|
|
|
}
|
2001-04-19 22:09:25 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
|
|
|
|
break; // Got a file name - break out of loop
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GSIArrayRemoveLastItem(_stack);
|
|
|
|
|
if (_currentFilePath != 0)
|
|
|
|
|
{
|
|
|
|
|
DESTROY(_currentFilePath);
|
|
|
|
|
}
|
2001-04-19 22:09:25 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
|
|
|
|
return AUTORELEASE(returnFileName);
|
1997-03-03 20:10:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end /* NSDirectoryEnumerator */
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Convenience methods for accessing named file attributes in a dictionary.
|
2002-09-16 11:30:22 +00:00
|
|
|
|
*/
|
|
|
|
|
@implementation NSDictionary(NSFileAttributes)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the file creation date attribute (or nil if not found).
|
|
|
|
|
*/
|
|
|
|
|
- (NSDate*) fileCreationDate
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
return [self objectForKey: NSFileCreationDate];
|
|
|
|
|
}
|
2001-04-19 22:09:25 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file extension hidden attribute (or NO if not found).
|
|
|
|
|
*/
|
|
|
|
|
- (BOOL) fileExtensionHidden
|
|
|
|
|
{
|
|
|
|
|
return [[self objectForKey: NSFileExtensionHidden] boolValue];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns HFS creator attribute (OS X).
|
|
|
|
|
*/
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (int) fileHFSCreatorCode
|
|
|
|
|
{
|
|
|
|
|
return [[self objectForKey: NSFileHFSCreatorCode] intValue];
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
/**
|
|
|
|
|
* Returns HFS type code attribute (OS X).
|
|
|
|
|
*/
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (int) fileHFSTypeCode
|
|
|
|
|
{
|
|
|
|
|
return [[self objectForKey: NSFileHFSTypeCode] intValue];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the file append only attribute (or NO if not found).
|
1997-03-03 20:10:10 +00:00
|
|
|
|
*/
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (BOOL) fileIsAppendOnly
|
|
|
|
|
{
|
|
|
|
|
return [[self objectForKey: NSFileAppendOnly] boolValue];
|
|
|
|
|
}
|
1997-03-03 20:10:10 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file immutable attribute (or NO if not found).
|
|
|
|
|
*/
|
|
|
|
|
- (BOOL) fileIsImmutable
|
|
|
|
|
{
|
|
|
|
|
return [[self objectForKey: NSFileImmutable] boolValue];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the size of the file, or NSNotFound if the file size attribute
|
|
|
|
|
* is not found in the dictionary.
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (unsigned long long) fileSize
|
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSNumber *n = [self objectForKey: NSFileSize];
|
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
return NSNotFound;
|
|
|
|
|
}
|
|
|
|
|
return [n unsignedLongLongValue];
|
1998-12-03 16:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file type attribute or nil if not present.
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (NSString*) fileType
|
|
|
|
|
{
|
|
|
|
|
return [self objectForKey: NSFileType];
|
|
|
|
|
}
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file owner account name attribute or nil if not present.
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (NSString*) fileOwnerAccountName
|
|
|
|
|
{
|
|
|
|
|
return [self objectForKey: NSFileOwnerAccountName];
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the numeric value of the NSFileOwnerAccountID attribute
|
|
|
|
|
* in the dictionary, or NSNotFound if the attribute is not present.
|
|
|
|
|
*/
|
|
|
|
|
- (unsigned long) fileOwnerAccountID
|
1998-12-03 16:20:31 +00:00
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSNumber *n = [self objectForKey: NSFileOwnerAccountID];
|
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
return NSNotFound;
|
|
|
|
|
}
|
|
|
|
|
return [n unsignedIntValue];
|
1998-12-03 16:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file group owner account name attribute or nil if not present.
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (NSString*) fileGroupOwnerAccountName
|
|
|
|
|
{
|
|
|
|
|
return [self objectForKey: NSFileGroupOwnerAccountName];
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the numeric value of the NSFileGroupOwnerAccountID attribute
|
|
|
|
|
* in the dictionary, or NSNotFound if the attribute is not present.
|
|
|
|
|
*/
|
|
|
|
|
- (unsigned long) fileGroupOwnerAccountID
|
1998-12-03 16:20:31 +00:00
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSNumber *n = [self objectForKey: NSFileGroupOwnerAccountID];
|
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
return NSNotFound;
|
|
|
|
|
}
|
|
|
|
|
return [n unsignedIntValue];
|
1998-12-03 16:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file modification date attribute (or nil if not found)
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (NSDate*) fileModificationDate
|
|
|
|
|
{
|
|
|
|
|
return [self objectForKey: NSFileModificationDate];
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file posix permissions attribute (or NSNotFound if
|
|
|
|
|
* the attribute is not present in the dictionary).
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (unsigned long) filePosixPermissions
|
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSNumber *n = [self objectForKey: NSFilePosixPermissions];
|
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
return NSNotFound;
|
|
|
|
|
}
|
|
|
|
|
return [n unsignedLongValue];
|
1998-12-03 16:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the file system number attribute (or NSNotFound if
|
|
|
|
|
* the attribute is not present in the dictionary).
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (unsigned long) fileSystemNumber
|
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSNumber *n = [self objectForKey: NSFileSystemNumber];
|
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
return NSNotFound;
|
|
|
|
|
}
|
|
|
|
|
return [n unsignedLongValue];
|
1998-12-03 16:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
/**
|
2005-02-02 09:43:29 +00:00
|
|
|
|
* Return the file system file identification number attribute
|
2002-09-16 11:30:22 +00:00
|
|
|
|
* or NSNotFound if the attribute is not present in the dictionary).
|
|
|
|
|
*/
|
1998-12-03 16:20:31 +00:00
|
|
|
|
- (unsigned long) fileSystemFileNumber
|
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSNumber *n = [self objectForKey: NSFileSystemFileNumber];
|
|
|
|
|
|
|
|
|
|
if (n == nil)
|
|
|
|
|
{
|
|
|
|
|
return NSNotFound;
|
|
|
|
|
}
|
|
|
|
|
return [n unsignedLongValue];
|
1998-12-03 16:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
@end
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
|
|
|
|
@implementation NSFileManager (PrivateMethods)
|
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) _copyFile: (NSString*)source
|
|
|
|
|
toFile: (NSString*)destination
|
2001-04-10 03:27:01 +00:00
|
|
|
|
handler: (id)handler
|
1998-02-05 22:06:20 +00:00
|
|
|
|
{
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(__MINGW32__)
|
2005-11-28 15:41:35 +00:00
|
|
|
|
if (CopyFileW([self fileSystemRepresentationWithPath: source],
|
|
|
|
|
[self fileSystemRepresentationWithPath: destination], NO))
|
2001-04-10 03:27:01 +00:00
|
|
|
|
{
|
|
|
|
|
return YES;
|
|
|
|
|
}
|
2003-02-11 10:26:17 +00:00
|
|
|
|
|
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot copy file"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
|
|
|
|
|
2001-04-10 03:27:01 +00:00
|
|
|
|
#else
|
|
|
|
|
NSDictionary *attributes;
|
|
|
|
|
int i;
|
|
|
|
|
int bufsize = 8096;
|
|
|
|
|
int sourceFd;
|
|
|
|
|
int destFd;
|
|
|
|
|
int fileSize;
|
|
|
|
|
int fileMode;
|
|
|
|
|
int rbytes;
|
|
|
|
|
int wbytes;
|
|
|
|
|
char buffer[bufsize];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
|
|
|
|
/* Assumes source is a file and exists! */
|
|
|
|
|
NSAssert1 ([self fileExistsAtPath: source],
|
2001-04-10 03:27:01 +00:00
|
|
|
|
@"source file '%@' does not exist!", source);
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
attributes = [self fileAttributesAtPath: source traverseLink: NO];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
NSAssert1 (attributes, @"could not get the attributes for file '%@'",
|
2001-04-10 03:27:01 +00:00
|
|
|
|
source);
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
2002-09-16 12:43:48 +00:00
|
|
|
|
fileSize = [attributes fileSize];
|
|
|
|
|
fileMode = [attributes filePosixPermissions];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
|
|
|
|
/* Open the source file. In case of error call the handler. */
|
2001-04-10 03:27:01 +00:00
|
|
|
|
sourceFd = open([self fileSystemRepresentationWithPath: source],
|
|
|
|
|
GSBINIO|O_RDONLY);
|
|
|
|
|
if (sourceFd < 0)
|
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot open file for reading"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
2001-04-10 03:27:01 +00:00
|
|
|
|
}
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
|
|
|
|
/* Open the destination file. In case of error call the handler. */
|
2001-04-10 03:27:01 +00:00
|
|
|
|
destFd = open([self fileSystemRepresentationWithPath: destination],
|
|
|
|
|
GSBINIO|O_WRONLY|O_CREAT|O_TRUNC, fileMode);
|
|
|
|
|
if (destFd < 0)
|
|
|
|
|
{
|
2005-02-02 09:43:29 +00:00
|
|
|
|
close (sourceFd);
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot open file for writing"
|
|
|
|
|
inPath: destination
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
/* Read bufsize bytes from source file and write them into the destination
|
|
|
|
|
file. In case of errors call the handler and abort the operation. */
|
2001-04-10 03:27:01 +00:00
|
|
|
|
for (i = 0; i < fileSize; i += rbytes)
|
|
|
|
|
{
|
1999-05-08 05:43:48 +00:00
|
|
|
|
rbytes = read (sourceFd, buffer, bufsize);
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (rbytes < 0)
|
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
close (sourceFd);
|
|
|
|
|
close (destFd);
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot read from file"
|
|
|
|
|
inPath: source
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
wbytes = write (destFd, buffer, rbytes);
|
2001-04-10 03:27:01 +00:00
|
|
|
|
if (wbytes != rbytes)
|
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
close (sourceFd);
|
|
|
|
|
close (destFd);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
return [self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot write to file"
|
|
|
|
|
inPath: destination
|
|
|
|
|
fromPath: source
|
|
|
|
|
toPath: destination];
|
|
|
|
|
}
|
2001-04-10 03:27:01 +00:00
|
|
|
|
}
|
1999-05-08 05:43:48 +00:00
|
|
|
|
close (sourceFd);
|
|
|
|
|
close (destFd);
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
return YES;
|
2001-04-10 03:27:01 +00:00
|
|
|
|
#endif
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
- (BOOL) _copyPath: (NSString*)source
|
|
|
|
|
toPath: (NSString*)destination
|
|
|
|
|
handler: handler
|
1998-02-05 22:06:20 +00:00
|
|
|
|
{
|
1999-06-17 19:09:25 +00:00
|
|
|
|
NSDirectoryEnumerator *enumerator;
|
|
|
|
|
NSString *dirEntry;
|
1999-06-18 10:28:11 +00:00
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
|
|
|
|
enumerator = [self enumeratorAtPath: source];
|
1999-06-17 19:09:25 +00:00
|
|
|
|
while ((dirEntry = [enumerator nextObject]))
|
|
|
|
|
{
|
|
|
|
|
NSString *sourceFile;
|
|
|
|
|
NSString *fileType;
|
|
|
|
|
NSString *destinationFile;
|
|
|
|
|
NSDictionary *attributes;
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
attributes = [enumerator fileAttributes];
|
2002-09-16 12:43:48 +00:00
|
|
|
|
fileType = [attributes fileType];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
sourceFile = [source stringByAppendingPathComponent: dirEntry];
|
|
|
|
|
destinationFile
|
1999-06-17 19:09:25 +00:00
|
|
|
|
= [destination stringByAppendingPathComponent: dirEntry];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
[self _sendToHandler: handler willProcessPath: sourceFile];
|
|
|
|
|
|
1999-06-17 19:09:25 +00:00
|
|
|
|
if ([fileType isEqual: NSFileTypeDirectory])
|
|
|
|
|
{
|
2006-03-08 13:49:06 +00:00
|
|
|
|
BOOL dirOK;
|
|
|
|
|
|
|
|
|
|
dirOK = [self createDirectoryAtPath: destinationFile
|
|
|
|
|
attributes: attributes];
|
|
|
|
|
if (dirOK == NO)
|
1999-06-17 19:09:25 +00:00
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
if (![self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: _lastError
|
|
|
|
|
inPath: destinationFile
|
|
|
|
|
fromPath: sourceFile
|
|
|
|
|
toPath: destinationFile])
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
2006-03-08 13:49:06 +00:00
|
|
|
|
/*
|
|
|
|
|
* We may have managed to create the directory but not set
|
|
|
|
|
* its attributes ... if so we can continue copying.
|
|
|
|
|
*/
|
|
|
|
|
if (![self fileExistsAtPath: destinationFile isDirectory: &dirOK])
|
|
|
|
|
{
|
|
|
|
|
dirOK = NO;
|
|
|
|
|
}
|
1999-06-17 19:09:25 +00:00
|
|
|
|
}
|
2006-03-08 13:49:06 +00:00
|
|
|
|
if (dirOK == YES)
|
1999-06-17 19:09:25 +00:00
|
|
|
|
{
|
1999-05-08 05:43:48 +00:00
|
|
|
|
[enumerator skipDescendents];
|
1999-06-17 19:09:25 +00:00
|
|
|
|
if (![self _copyPath: sourceFile
|
2003-02-11 10:26:17 +00:00
|
|
|
|
toPath: destinationFile
|
|
|
|
|
handler: handler])
|
1999-06-17 19:09:25 +00:00
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ([fileType isEqual: NSFileTypeRegular])
|
|
|
|
|
{
|
|
|
|
|
if (![self _copyFile: sourceFile
|
|
|
|
|
toFile: destinationFile
|
|
|
|
|
handler: handler])
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
else if ([fileType isEqual: NSFileTypeSymbolicLink])
|
|
|
|
|
{
|
2002-03-09 12:10:08 +00:00
|
|
|
|
NSString *path;
|
|
|
|
|
|
|
|
|
|
path = [self pathContentOfSymbolicLinkAtPath: sourceFile];
|
1999-05-08 05:43:48 +00:00
|
|
|
|
if (![self createSymbolicLinkAtPath: destinationFile
|
2002-03-09 12:10:08 +00:00
|
|
|
|
pathContent: path])
|
1999-06-17 19:09:25 +00:00
|
|
|
|
{
|
2003-02-11 10:26:17 +00:00
|
|
|
|
if (![self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot create symbolic link"
|
|
|
|
|
inPath: sourceFile
|
|
|
|
|
fromPath: sourceFile
|
|
|
|
|
toPath: destinationFile])
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1999-06-17 19:09:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
1999-06-18 10:28:11 +00:00
|
|
|
|
NSString *s;
|
|
|
|
|
|
|
|
|
|
s = [NSString stringWithFormat: @"cannot copy file type '%@'",
|
|
|
|
|
fileType];
|
1999-09-16 07:21:34 +00:00
|
|
|
|
ASSIGN(_lastError, s);
|
1999-06-18 10:28:11 +00:00
|
|
|
|
NSLog(@"%@: %@", sourceFile, s);
|
|
|
|
|
continue;
|
1999-06-17 19:09:25 +00:00
|
|
|
|
}
|
1999-05-08 05:43:48 +00:00
|
|
|
|
[self changeFileAttributes: attributes atPath: destinationFile];
|
1999-06-17 19:09:25 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
RELEASE(pool);
|
1998-02-05 22:06:20 +00:00
|
|
|
|
|
1999-05-08 05:43:48 +00:00
|
|
|
|
return YES;
|
1998-02-05 22:06:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-17 11:23:29 +00:00
|
|
|
|
- (BOOL) _linkPath: (NSString*)source
|
|
|
|
|
toPath: (NSString*)destination
|
|
|
|
|
handler: handler
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_LINK
|
|
|
|
|
NSDirectoryEnumerator *enumerator;
|
|
|
|
|
NSString *dirEntry;
|
|
|
|
|
CREATE_AUTORELEASE_POOL(pool);
|
|
|
|
|
|
|
|
|
|
enumerator = [self enumeratorAtPath: source];
|
|
|
|
|
while ((dirEntry = [enumerator nextObject]))
|
|
|
|
|
{
|
|
|
|
|
NSString *sourceFile;
|
|
|
|
|
NSString *fileType;
|
|
|
|
|
NSString *destinationFile;
|
|
|
|
|
NSDictionary *attributes;
|
|
|
|
|
|
|
|
|
|
attributes = [enumerator fileAttributes];
|
|
|
|
|
fileType = [attributes fileType];
|
|
|
|
|
sourceFile = [source stringByAppendingPathComponent: dirEntry];
|
|
|
|
|
destinationFile
|
|
|
|
|
= [destination stringByAppendingPathComponent: dirEntry];
|
|
|
|
|
|
|
|
|
|
[self _sendToHandler: handler willProcessPath: sourceFile];
|
|
|
|
|
|
|
|
|
|
if ([fileType isEqual: NSFileTypeDirectory] == YES)
|
|
|
|
|
{
|
|
|
|
|
if ([self createDirectoryAtPath: destinationFile
|
|
|
|
|
attributes: attributes] == NO)
|
|
|
|
|
{
|
|
|
|
|
if ([self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: _lastError
|
|
|
|
|
inPath: destinationFile
|
|
|
|
|
fromPath: sourceFile
|
|
|
|
|
toPath: destinationFile] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
[enumerator skipDescendents];
|
|
|
|
|
if ([self _linkPath: sourceFile
|
|
|
|
|
toPath: destinationFile
|
|
|
|
|
handler: handler] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ([fileType isEqual: NSFileTypeSymbolicLink])
|
|
|
|
|
{
|
|
|
|
|
NSString *path;
|
|
|
|
|
|
|
|
|
|
path = [self pathContentOfSymbolicLinkAtPath: sourceFile];
|
|
|
|
|
if ([self createSymbolicLinkAtPath: destinationFile
|
|
|
|
|
pathContent: path] == NO)
|
|
|
|
|
{
|
|
|
|
|
if ([self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot create symbolic link"
|
|
|
|
|
inPath: sourceFile
|
|
|
|
|
fromPath: sourceFile
|
|
|
|
|
toPath: destinationFile] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-06-04 18:58:05 +00:00
|
|
|
|
if (link([self fileSystemRepresentationWithPath: sourceFile],
|
|
|
|
|
[self fileSystemRepresentationWithPath: destinationFile]) < 0)
|
2003-04-17 11:23:29 +00:00
|
|
|
|
{
|
|
|
|
|
if ([self _proceedAccordingToHandler: handler
|
|
|
|
|
forError: @"cannot create hard link"
|
|
|
|
|
inPath: sourceFile
|
|
|
|
|
fromPath: sourceFile
|
|
|
|
|
toPath: destinationFile] == NO)
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
[self changeFileAttributes: attributes atPath: destinationFile];
|
|
|
|
|
}
|
|
|
|
|
RELEASE(pool);
|
|
|
|
|
return YES;
|
|
|
|
|
#else
|
|
|
|
|
return NO;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2003-02-11 10:26:17 +00:00
|
|
|
|
- (void) _sendToHandler: (id) handler
|
|
|
|
|
willProcessPath: (NSString*) path
|
|
|
|
|
{
|
|
|
|
|
if ([handler respondsToSelector: @selector (fileManager:willProcessPath:)])
|
|
|
|
|
{
|
|
|
|
|
[handler fileManager: self willProcessPath: path];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) _proceedAccordingToHandler: (id) handler
|
|
|
|
|
forError: (NSString*) error
|
|
|
|
|
inPath: (NSString*) path
|
|
|
|
|
{
|
|
|
|
|
if ([handler respondsToSelector:
|
|
|
|
|
@selector (fileManager:shouldProceedAfterError:)])
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
path, @"Path",
|
|
|
|
|
error, @"Error", nil];
|
|
|
|
|
return [handler fileManager: self
|
|
|
|
|
shouldProceedAfterError: errorInfo];
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) _proceedAccordingToHandler: (id) handler
|
|
|
|
|
forError: (NSString*) error
|
|
|
|
|
inPath: (NSString*) path
|
|
|
|
|
fromPath: (NSString*) fromPath
|
|
|
|
|
toPath: (NSString*) toPath
|
|
|
|
|
{
|
|
|
|
|
if ([handler respondsToSelector:
|
|
|
|
|
@selector (fileManager:shouldProceedAfterError:)])
|
|
|
|
|
{
|
|
|
|
|
NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
|
path, @"Path",
|
|
|
|
|
fromPath, @"FromPath",
|
|
|
|
|
toPath, @"ToPath",
|
|
|
|
|
error, @"Error", nil];
|
|
|
|
|
return [handler fileManager: self
|
|
|
|
|
shouldProceedAfterError: errorInfo];
|
|
|
|
|
}
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
@end /* NSFileManager (PrivateMethods) */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@implementation GSAttrDictionary
|
2001-10-17 03:45:32 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
static NSSet *fileKeys = nil;
|
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
+ (NSDictionary*) attributesAt: (const _CHAR*)lpath
|
|
|
|
|
traverseLink: (BOOL)traverse
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
GSAttrDictionary *d;
|
2006-02-17 06:31:04 +00:00
|
|
|
|
unsigned l = 0;
|
|
|
|
|
unsigned i;
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lpath == 0 || *lpath == 0)
|
2003-02-11 09:13:24 +00:00
|
|
|
|
{
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
2006-02-17 06:31:04 +00:00
|
|
|
|
while (lpath[l] != 0)
|
|
|
|
|
{
|
|
|
|
|
l++;
|
|
|
|
|
}
|
|
|
|
|
d = (GSAttrDictionary*)NSAllocateObject(self, (l+1)*sizeof(_CHAR),
|
|
|
|
|
NSDefaultMallocZone());
|
2005-02-18 06:13:20 +00:00
|
|
|
|
|
2005-10-11 19:09:26 +00:00
|
|
|
|
#if defined(S_IFLNK) && !defined(__MINGW32__)
|
2002-09-16 11:30:22 +00:00
|
|
|
|
if (traverse == NO)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (lstat(lpath, &d->statbuf) != 0)
|
2001-04-10 03:27:01 +00:00
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
DESTROY(d);
|
2001-04-10 03:27:01 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2002-09-16 11:30:22 +00:00
|
|
|
|
#endif
|
2005-02-18 06:13:20 +00:00
|
|
|
|
if (_STAT(lpath, &d->statbuf) != 0)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2002-09-16 11:30:22 +00:00
|
|
|
|
DESTROY(d);
|
1999-06-18 10:28:11 +00:00
|
|
|
|
}
|
2006-02-18 20:53:01 +00:00
|
|
|
|
if (d != nil)
|
2006-02-17 06:31:04 +00:00
|
|
|
|
{
|
2006-02-18 20:53:01 +00:00
|
|
|
|
for (i = 0; i <= l; i++)
|
|
|
|
|
{
|
|
|
|
|
d->_path[i] = lpath[i];
|
|
|
|
|
}
|
2006-02-17 06:31:04 +00:00
|
|
|
|
}
|
2005-02-02 09:43:29 +00:00
|
|
|
|
return AUTORELEASE(d);
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (void) initialize
|
|
|
|
|
{
|
|
|
|
|
if (fileKeys == nil)
|
|
|
|
|
{
|
|
|
|
|
fileKeys = [NSSet setWithObjects:
|
|
|
|
|
NSFileAppendOnly,
|
|
|
|
|
NSFileCreationDate,
|
|
|
|
|
NSFileDeviceIdentifier,
|
|
|
|
|
NSFileExtensionHidden,
|
|
|
|
|
NSFileGroupOwnerAccountName,
|
|
|
|
|
NSFileGroupOwnerAccountID,
|
|
|
|
|
NSFileHFSCreatorCode,
|
|
|
|
|
NSFileHFSTypeCode,
|
|
|
|
|
NSFileImmutable,
|
|
|
|
|
NSFileModificationDate,
|
|
|
|
|
NSFileOwnerAccountName,
|
|
|
|
|
NSFileOwnerAccountID,
|
|
|
|
|
NSFilePosixPermissions,
|
|
|
|
|
NSFileReferenceCount,
|
|
|
|
|
NSFileSize,
|
|
|
|
|
NSFileSystemFileNumber,
|
|
|
|
|
NSFileSystemNumber,
|
|
|
|
|
NSFileType,
|
|
|
|
|
nil];
|
|
|
|
|
RETAIN(fileKeys);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned int) count
|
|
|
|
|
{
|
|
|
|
|
return [fileKeys count];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSDate*) fileCreationDate
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
|
* FIXME ... not sure there is any way to get a creation date :-(
|
|
|
|
|
* Use the earlier of ctime or mtime
|
|
|
|
|
*/
|
|
|
|
|
if (statbuf.st_ctime < statbuf.st_mtime)
|
|
|
|
|
return [NSDate dateWithTimeIntervalSince1970: statbuf.st_ctime];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
else
|
2002-09-16 11:30:22 +00:00
|
|
|
|
return [NSDate dateWithTimeIntervalSince1970: statbuf.st_mtime];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL) fileExtensionHidden
|
|
|
|
|
{
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (unsigned long) fileGroupOwnerAccountID
|
|
|
|
|
{
|
|
|
|
|
return statbuf.st_gid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSString*) fileGroupOwnerAccountName
|
|
|
|
|
{
|
2006-02-17 06:39:21 +00:00
|
|
|
|
NSString *group = @"UnknownGroup";
|
|
|
|
|
|
|
|
|
|
#if defined(__MINGW32__)
|
|
|
|
|
DWORD returnCode = 0;
|
|
|
|
|
PSID sidOwner;
|
|
|
|
|
BOOL result = TRUE;
|
|
|
|
|
_CHAR account[BUFSIZ];
|
|
|
|
|
_CHAR domain[BUFSIZ];
|
|
|
|
|
DWORD accountSize = 1024;
|
|
|
|
|
DWORD domainSize = 1024;
|
|
|
|
|
SID_NAME_USE eUse = SidTypeUnknown;
|
|
|
|
|
HANDLE hFile;
|
|
|
|
|
PSECURITY_DESCRIPTOR pSD;
|
|
|
|
|
|
|
|
|
|
// Get the handle of the file object.
|
|
|
|
|
hFile = CreateFileW(
|
|
|
|
|
_path,
|
|
|
|
|
GENERIC_READ,
|
|
|
|
|
FILE_SHARE_READ,
|
|
|
|
|
0,
|
|
|
|
|
OPEN_EXISTING,
|
2006-03-04 07:25:52 +00:00
|
|
|
|
FILE_FLAG_BACKUP_SEMANTICS,
|
2006-02-17 06:39:21 +00:00
|
|
|
|
0);
|
|
|
|
|
|
|
|
|
|
// Check GetLastError for CreateFile error code.
|
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwErrorCode = 0;
|
|
|
|
|
|
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
|
NSDebugMLog(@"Error %d getting file handle for '%S'",
|
|
|
|
|
dwErrorCode, _path);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the group SID of the file.
|
|
|
|
|
returnCode = GetSecurityInfo(
|
|
|
|
|
hFile,
|
|
|
|
|
SE_FILE_OBJECT,
|
|
|
|
|
GROUP_SECURITY_INFORMATION,
|
|
|
|
|
0,
|
|
|
|
|
&sidOwner,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
&pSD);
|
|
|
|
|
|
|
|
|
|
CloseHandle(hFile);
|
|
|
|
|
|
|
|
|
|
// Check GetLastError for GetSecurityInfo error condition.
|
|
|
|
|
if (returnCode != ERROR_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwErrorCode = 0;
|
|
|
|
|
|
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
|
NSDebugMLog(@"Error %d getting security info for '%S'",
|
|
|
|
|
dwErrorCode, _path);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// First call to LookupAccountSid to get the buffer sizes.
|
|
|
|
|
result = LookupAccountSidW(
|
|
|
|
|
0, // local computer
|
|
|
|
|
sidOwner,
|
|
|
|
|
account,
|
|
|
|
|
(LPDWORD)&accountSize,
|
|
|
|
|
domain,
|
|
|
|
|
(LPDWORD)&domainSize,
|
|
|
|
|
&eUse);
|
|
|
|
|
|
|
|
|
|
// Check GetLastError for LookupAccountSid error condition.
|
|
|
|
|
if (result == FALSE)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwErrorCode = 0;
|
|
|
|
|
|
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
|
if (dwErrorCode == ERROR_NONE_MAPPED)
|
|
|
|
|
NSDebugMLog(@"Error %d in LookupAccountSid for '%S'", _path);
|
|
|
|
|
else
|
|
|
|
|
NSDebugMLog(@"Error %d getting security info for '%S'",
|
|
|
|
|
dwErrorCode, _path);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (accountSize >= 1024)
|
|
|
|
|
{
|
|
|
|
|
NSDebugMLog(@"Account name for '%S' is unreasonably long", _path);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
return [NSString stringWithCharacters: account length: accountSize];
|
|
|
|
|
#else
|
2004-07-10 03:19:56 +00:00
|
|
|
|
#if defined(HAVE_GRP_H)
|
2002-09-16 11:30:22 +00:00
|
|
|
|
struct group *gp;
|
|
|
|
|
|
|
|
|
|
gp = getgrgid(statbuf.st_gid);
|
|
|
|
|
if (gp != 0)
|
1999-06-18 10:28:11 +00:00
|
|
|
|
{
|
2006-02-17 06:39:21 +00:00
|
|
|
|
group = [NSString stringWithCString: gp->gr_name];
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2006-02-17 06:39:21 +00:00
|
|
|
|
#endif
|
|
|
|
|
return group;
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
2002-05-10 12:23:32 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (int) fileHFSCreatorCode
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (int) fileHFSTypeCode
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (BOOL) fileIsAppendOnly
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (BOOL) fileIsImmutable
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (NSDate*) fileModificationDate
|
|
|
|
|
{
|
|
|
|
|
return [NSDate dateWithTimeIntervalSince1970: statbuf.st_mtime];
|
|
|
|
|
}
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (unsigned long) filePosixPermissions
|
|
|
|
|
{
|
|
|
|
|
return (statbuf.st_mode & ~S_IFMT);
|
|
|
|
|
}
|
2002-05-10 12:23:32 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (unsigned long) fileOwnerAccountID
|
|
|
|
|
{
|
|
|
|
|
return statbuf.st_uid;
|
|
|
|
|
}
|
2002-05-10 12:23:32 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (NSString*) fileOwnerAccountName
|
|
|
|
|
{
|
2006-02-17 06:31:04 +00:00
|
|
|
|
NSString *owner = @"UnknownUser";
|
|
|
|
|
|
|
|
|
|
#if defined(__MINGW32__)
|
|
|
|
|
DWORD returnCode = 0;
|
|
|
|
|
PSID sidOwner;
|
|
|
|
|
BOOL result = TRUE;
|
|
|
|
|
_CHAR account[BUFSIZ];
|
|
|
|
|
_CHAR domain[BUFSIZ];
|
|
|
|
|
DWORD accountSize = 1024;
|
|
|
|
|
DWORD domainSize = 1024;
|
2002-09-16 11:30:22 +00:00
|
|
|
|
SID_NAME_USE eUse = SidTypeUnknown;
|
|
|
|
|
HANDLE hFile;
|
|
|
|
|
PSECURITY_DESCRIPTOR pSD;
|
|
|
|
|
|
|
|
|
|
// Get the handle of the file object.
|
2005-11-05 16:20:19 +00:00
|
|
|
|
hFile = CreateFileW(
|
2006-02-17 06:31:04 +00:00
|
|
|
|
_path,
|
2005-02-02 09:43:29 +00:00
|
|
|
|
GENERIC_READ,
|
|
|
|
|
FILE_SHARE_READ,
|
|
|
|
|
0,
|
|
|
|
|
OPEN_EXISTING,
|
2006-03-04 07:25:52 +00:00
|
|
|
|
FILE_FLAG_BACKUP_SEMANTICS,
|
2005-02-02 09:43:29 +00:00
|
|
|
|
0);
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
|
|
|
|
// Check GetLastError for CreateFile error code.
|
2005-02-02 09:43:29 +00:00
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwErrorCode = 0;
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
dwErrorCode = GetLastError();
|
2006-02-17 06:31:04 +00:00
|
|
|
|
NSDebugMLog(@"Error %d getting file handle for '%S'",
|
|
|
|
|
dwErrorCode, _path);
|
|
|
|
|
return owner;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
|
|
|
|
// Get the owner SID of the file.
|
2006-02-17 06:31:04 +00:00
|
|
|
|
returnCode = GetSecurityInfo(
|
2005-02-02 09:43:29 +00:00
|
|
|
|
hFile,
|
|
|
|
|
SE_FILE_OBJECT,
|
|
|
|
|
OWNER_SECURITY_INFORMATION,
|
2006-02-17 06:31:04 +00:00
|
|
|
|
&sidOwner,
|
2005-02-02 09:43:29 +00:00
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
0,
|
|
|
|
|
&pSD);
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
2006-02-17 06:31:04 +00:00
|
|
|
|
CloseHandle(hFile);
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
// Check GetLastError for GetSecurityInfo error condition.
|
2006-02-17 06:31:04 +00:00
|
|
|
|
if (returnCode != ERROR_SUCCESS)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD dwErrorCode = 0;
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
dwErrorCode = GetLastError();
|
2006-02-17 06:31:04 +00:00
|
|
|
|
NSDebugMLog(@"Error %d getting security info for '%S'",
|
|
|
|
|
dwErrorCode, _path);
|
|
|
|
|
return owner;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
|
|
|
|
// First call to LookupAccountSid to get the buffer sizes.
|
2006-02-17 06:31:04 +00:00
|
|
|
|
result = LookupAccountSidW(
|
2005-02-02 09:43:29 +00:00
|
|
|
|
0, // local computer
|
2006-02-17 06:31:04 +00:00
|
|
|
|
sidOwner,
|
|
|
|
|
account,
|
|
|
|
|
(LPDWORD)&accountSize,
|
|
|
|
|
domain,
|
|
|
|
|
(LPDWORD)&domainSize,
|
2005-02-02 09:43:29 +00:00
|
|
|
|
&eUse);
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
// Check GetLastError for LookupAccountSid error condition.
|
2006-02-17 06:31:04 +00:00
|
|
|
|
if (result == FALSE)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
|
|
|
|
DWORD dwErrorCode = 0;
|
2002-05-10 12:23:32 +00:00
|
|
|
|
|
2005-02-02 09:43:29 +00:00
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
|
if (dwErrorCode == ERROR_NONE_MAPPED)
|
2006-02-17 06:31:04 +00:00
|
|
|
|
NSDebugMLog(@"Error %d in LookupAccountSid for '%S'", _path);
|
2005-02-02 09:43:29 +00:00
|
|
|
|
else
|
2006-02-17 06:31:04 +00:00
|
|
|
|
NSDebugMLog(@"Error %d getting security info for '%S'",
|
|
|
|
|
dwErrorCode, _path);
|
|
|
|
|
return owner;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2006-02-17 06:31:04 +00:00
|
|
|
|
|
|
|
|
|
if (accountSize >= 1024)
|
2005-02-02 09:43:29 +00:00
|
|
|
|
{
|
2006-02-17 06:31:04 +00:00
|
|
|
|
NSDebugMLog(@"Account name for '%S' is unreasonably long", _path);
|
|
|
|
|
return owner;
|
2005-02-02 09:43:29 +00:00
|
|
|
|
}
|
2006-02-17 06:31:04 +00:00
|
|
|
|
return [NSString stringWithCharacters: account length: accountSize];
|
|
|
|
|
#else
|
2005-02-02 09:43:29 +00:00
|
|
|
|
#ifdef HAVE_PWD_H
|
2002-09-16 11:30:22 +00:00
|
|
|
|
struct passwd *pw;
|
|
|
|
|
|
|
|
|
|
pw = getpwuid(statbuf.st_uid);
|
|
|
|
|
|
|
|
|
|
if (pw != 0)
|
|
|
|
|
{
|
2006-02-17 06:31:04 +00:00
|
|
|
|
owner = [NSString stringWithCString: pw->pw_name];
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
#endif /* HAVE_PWD_H */
|
2006-02-17 06:31:04 +00:00
|
|
|
|
#endif
|
|
|
|
|
return owner;
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (unsigned long long) fileSize
|
|
|
|
|
{
|
|
|
|
|
return statbuf.st_size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned long) fileSystemFileNumber
|
|
|
|
|
{
|
|
|
|
|
return statbuf.st_ino;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (unsigned long) fileSystemNumber
|
|
|
|
|
{
|
|
|
|
|
return statbuf.st_dev;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSString*) fileType
|
|
|
|
|
{
|
|
|
|
|
switch (statbuf.st_mode & S_IFMT)
|
|
|
|
|
{
|
|
|
|
|
case S_IFREG: return NSFileTypeRegular;
|
|
|
|
|
case S_IFDIR: return NSFileTypeDirectory;
|
|
|
|
|
case S_IFCHR: return NSFileTypeCharacterSpecial;
|
|
|
|
|
case S_IFBLK: return NSFileTypeBlockSpecial;
|
|
|
|
|
#ifdef S_IFLNK
|
|
|
|
|
case S_IFLNK: return NSFileTypeSymbolicLink;
|
2001-10-17 03:45:32 +00:00
|
|
|
|
#endif
|
2002-09-16 11:30:22 +00:00
|
|
|
|
case S_IFIFO: return NSFileTypeFifo;
|
|
|
|
|
#ifdef S_IFSOCK
|
|
|
|
|
case S_IFSOCK: return NSFileTypeSocket;
|
1999-06-18 10:28:11 +00:00
|
|
|
|
#endif
|
2002-09-16 11:30:22 +00:00
|
|
|
|
default: return NSFileTypeUnknown;
|
1999-06-18 10:28:11 +00:00
|
|
|
|
}
|
2002-09-16 11:30:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSEnumerator*) keyEnumerator
|
|
|
|
|
{
|
|
|
|
|
return [fileKeys objectEnumerator];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSEnumerator*) objectEnumerator
|
|
|
|
|
{
|
|
|
|
|
return [GSAttrDictionaryEnumerator enumeratorFor: self];
|
|
|
|
|
}
|
|
|
|
|
|
2005-07-08 11:48:37 +00:00
|
|
|
|
- (id) objectForKey: (id)key
|
2002-09-16 11:30:22 +00:00
|
|
|
|
{
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
while (key != 0 && count < 2)
|
|
|
|
|
{
|
|
|
|
|
if (key == NSFileAppendOnly)
|
|
|
|
|
return [NSNumber numberWithBool: [self fileIsAppendOnly]];
|
|
|
|
|
if (key == NSFileCreationDate)
|
|
|
|
|
return [self fileCreationDate];
|
|
|
|
|
if (key == NSFileDeviceIdentifier)
|
|
|
|
|
return [NSNumber numberWithUnsignedInt: statbuf.st_dev];
|
|
|
|
|
if (key == NSFileExtensionHidden)
|
|
|
|
|
return [NSNumber numberWithBool: [self fileExtensionHidden]];
|
|
|
|
|
if (key == NSFileGroupOwnerAccountName)
|
|
|
|
|
return [self fileGroupOwnerAccountName];
|
|
|
|
|
if (key == NSFileGroupOwnerAccountID)
|
|
|
|
|
return [NSNumber numberWithInt: [self fileGroupOwnerAccountID]];
|
|
|
|
|
if (key == NSFileHFSCreatorCode)
|
|
|
|
|
return [NSNumber numberWithInt: [self fileHFSCreatorCode]];
|
|
|
|
|
if (key == NSFileHFSTypeCode)
|
|
|
|
|
return [NSNumber numberWithInt: [self fileHFSTypeCode]];
|
|
|
|
|
if (key == NSFileImmutable)
|
|
|
|
|
return [NSNumber numberWithBool: [self fileIsImmutable]];
|
|
|
|
|
if (key == NSFileModificationDate)
|
|
|
|
|
return [self fileModificationDate];
|
|
|
|
|
if (key == NSFileOwnerAccountName)
|
|
|
|
|
return [self fileOwnerAccountName];
|
|
|
|
|
if (key == NSFileOwnerAccountID)
|
|
|
|
|
return [NSNumber numberWithInt: [self fileOwnerAccountID]];
|
|
|
|
|
if (key == NSFilePosixPermissions)
|
|
|
|
|
return [NSNumber numberWithUnsignedInt: [self filePosixPermissions]];
|
|
|
|
|
if (key == NSFileReferenceCount)
|
|
|
|
|
return [NSNumber numberWithUnsignedInt: statbuf.st_nlink];
|
|
|
|
|
if (key == NSFileSize)
|
|
|
|
|
return [NSNumber numberWithUnsignedLongLong: [self fileSize]];
|
|
|
|
|
if (key == NSFileSystemFileNumber)
|
|
|
|
|
return [NSNumber numberWithUnsignedInt: [self fileSystemFileNumber]];
|
|
|
|
|
if (key == NSFileSystemNumber)
|
|
|
|
|
return [NSNumber numberWithUnsignedInt: [self fileSystemNumber]];
|
|
|
|
|
if (key == NSFileType)
|
|
|
|
|
return [self fileType];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
|
|
|
|
/*
|
2002-09-16 11:30:22 +00:00
|
|
|
|
* Now, if we didn't get an exact pointer match, check for
|
|
|
|
|
* string equalities and ensure we get an exact match next
|
|
|
|
|
* time round the loop.
|
1999-06-18 10:28:11 +00:00
|
|
|
|
*/
|
2002-09-16 11:30:22 +00:00
|
|
|
|
count++;
|
|
|
|
|
key = [fileKeys member: key];
|
1999-06-18 10:28:11 +00:00
|
|
|
|
}
|
2002-09-16 11:30:22 +00:00
|
|
|
|
if (count >= 2)
|
|
|
|
|
{
|
|
|
|
|
NSLog(@"Warning ... key '%@' not handled", key);
|
|
|
|
|
}
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
1999-06-18 10:28:11 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
@end /* GSAttrDictionary */
|
|
|
|
|
|
|
|
|
|
@implementation GSAttrDictionaryEnumerator
|
|
|
|
|
+ (NSEnumerator*) enumeratorFor: (NSDictionary*)d
|
|
|
|
|
{
|
|
|
|
|
GSAttrDictionaryEnumerator *e;
|
|
|
|
|
|
|
|
|
|
e = (GSAttrDictionaryEnumerator*)
|
|
|
|
|
NSAllocateObject(self, 0, NSDefaultMallocZone());
|
|
|
|
|
e->dictionary = RETAIN(d);
|
|
|
|
|
e->enumerator = RETAIN([fileKeys objectEnumerator]);
|
|
|
|
|
return AUTORELEASE(e);
|
1999-06-18 10:28:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (void) dealloc
|
|
|
|
|
{
|
|
|
|
|
RELEASE(enumerator);
|
|
|
|
|
RELEASE(dictionary);
|
|
|
|
|
[super dealloc];
|
|
|
|
|
}
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
- (id) nextObject
|
|
|
|
|
{
|
|
|
|
|
NSString *key = [enumerator nextObject];
|
|
|
|
|
id val = nil;
|
|
|
|
|
|
|
|
|
|
if (key != nil)
|
|
|
|
|
{
|
|
|
|
|
val = [dictionary objectForKey: key];
|
|
|
|
|
}
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
@end
|
2002-09-15 08:55:29 +00:00
|
|
|
|
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSString * const NSFileAppendOnly = @"NSFileAppendOnly";
|
2002-09-15 08:55:29 +00:00
|
|
|
|
NSString * const NSFileCreationDate = @"NSFileCreationDate";
|
|
|
|
|
NSString * const NSFileDeviceIdentifier = @"NSFileDeviceIdentifier";
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSString * const NSFileExtensionHidden = @"NSFileExtensionHidden";
|
|
|
|
|
NSString * const NSFileGroupOwnerAccountID = @"NSFileGroupOwnerAccountID";
|
2002-09-15 08:55:29 +00:00
|
|
|
|
NSString * const NSFileGroupOwnerAccountName = @"NSFileGroupOwnerAccountName";
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSString * const NSFileHFSCreatorCode = @"NSFileHFSCreatorCode";
|
|
|
|
|
NSString * const NSFileHFSTypeCode = @"NSFileHFSTypeCode";
|
|
|
|
|
NSString * const NSFileImmutable = @"NSFileImmutable";
|
2002-09-15 08:55:29 +00:00
|
|
|
|
NSString * const NSFileModificationDate = @"NSFileModificationDate";
|
2002-09-16 11:30:22 +00:00
|
|
|
|
NSString * const NSFileOwnerAccountID = @"NSFileOwnerAccountID";
|
2002-09-15 08:55:29 +00:00
|
|
|
|
NSString * const NSFileOwnerAccountName = @"NSFileOwnerAccountName";
|
|
|
|
|
NSString * const NSFilePosixPermissions = @"NSFilePosixPermissions";
|
|
|
|
|
NSString * const NSFileReferenceCount = @"NSFileReferenceCount";
|
|
|
|
|
NSString * const NSFileSize = @"NSFileSize";
|
|
|
|
|
NSString * const NSFileSystemFileNumber = @"NSFileSystemFileNumber";
|
|
|
|
|
NSString * const NSFileSystemFreeNodes = @"NSFileSystemFreeNodes";
|
|
|
|
|
NSString * const NSFileSystemFreeSize = @"NSFileSystemFreeSize";
|
|
|
|
|
NSString * const NSFileSystemNodes = @"NSFileSystemNodes";
|
|
|
|
|
NSString * const NSFileSystemNumber = @"NSFileSystemNumber";
|
|
|
|
|
NSString * const NSFileSystemSize = @"NSFileSystemSize";
|
|
|
|
|
NSString * const NSFileType = @"NSFileType";
|
|
|
|
|
NSString * const NSFileTypeBlockSpecial = @"NSFileTypeBlockSpecial";
|
|
|
|
|
NSString * const NSFileTypeCharacterSpecial = @"NSFileTypeCharacterSpecial";
|
|
|
|
|
NSString * const NSFileTypeDirectory = @"NSFileTypeDirectory";
|
|
|
|
|
NSString * const NSFileTypeFifo = @"NSFileTypeFifo";
|
|
|
|
|
NSString * const NSFileTypeRegular = @"NSFileTypeRegular";
|
|
|
|
|
NSString * const NSFileTypeSocket = @"NSFileTypeSocket";
|
|
|
|
|
NSString * const NSFileTypeSymbolicLink = @"NSFileTypeSymbolicLink";
|
|
|
|
|
NSString * const NSFileTypeUnknown = @"NSFileTypeUnknown";
|
2002-09-16 11:30:22 +00:00
|
|
|
|
|
|
|
|
|
|