mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 04:34:48 +00:00
240 lines
7.8 KiB
Plaintext
240 lines
7.8 KiB
Plaintext
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#import <Cocoa/Cocoa.h>
|
|
#import <Carbon/Carbon.h>
|
|
#include <unistd.h>
|
|
#include "platform/platform.h"
|
|
#include "console/console.h"
|
|
#include "core/stringTable.h"
|
|
#include "platform/platformInput.h"
|
|
#include "platform/threads/thread.h"
|
|
|
|
#pragma mark ---- Various Directories ----
|
|
//-----------------------------------------------------------------------------
|
|
const char* Platform::getUserDataDirectory()
|
|
{
|
|
// application support directory is most in line with the current usages of this function.
|
|
// this may change with later usage
|
|
// perhaps the user data directory should be pref-controlled?
|
|
NSString *nsDataDir = [@"~/Library/Application Support/" stringByStandardizingPath];
|
|
return StringTable->insert([nsDataDir UTF8String]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
const char* Platform::getUserHomeDirectory()
|
|
{
|
|
return StringTable->insert([[@"~/" stringByStandardizingPath] UTF8String]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
StringTableEntry osGetTemporaryDirectory()
|
|
{
|
|
NSString *tdir = NSTemporaryDirectory();
|
|
const char *path = [tdir UTF8String];
|
|
return StringTable->insert(path);
|
|
}
|
|
|
|
#pragma mark ---- Administrator ----
|
|
//-----------------------------------------------------------------------------
|
|
bool Platform::getUserIsAdministrator()
|
|
{
|
|
// if we can write to /Library, we're probably an admin
|
|
// HACK: this is not really very good, because people can chmod Library.
|
|
return (access("/Library", W_OK) == 0);
|
|
}
|
|
|
|
#pragma mark ---- Cosmetic ----
|
|
//-----------------------------------------------------------------------------
|
|
bool Platform::displaySplashWindow()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
#pragma mark ---- File IO ----
|
|
//-----------------------------------------------------------------------------
|
|
bool dPathCopy(const char* source, const char* dest, bool nooverwrite)
|
|
{
|
|
NSFileManager *manager = [NSFileManager defaultManager];
|
|
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
|
|
NSString *nsource = [[NSString stringWithUTF8String:source] stringByStandardizingPath];
|
|
NSString *ndest = [[NSString stringWithUTF8String:dest] stringByStandardizingPath];
|
|
NSString *ndestFolder = [ndest stringByDeletingLastPathComponent];
|
|
|
|
if(! [manager fileExistsAtPath:nsource])
|
|
{
|
|
Con::errorf("dPathCopy: no file exists at %s",source);
|
|
return false;
|
|
}
|
|
|
|
if( [manager fileExistsAtPath:ndest] )
|
|
{
|
|
if(nooverwrite)
|
|
{
|
|
Con::errorf("dPathCopy: file already exists at %s",dest);
|
|
return false;
|
|
}
|
|
Con::warnf("Deleting files at path: %s", dest);
|
|
bool deleted = [manager removeFileAtPath:ndest handler:nil];
|
|
if(!deleted)
|
|
{
|
|
Con::errorf("Copy failed! Could not delete files at path: %s", dest);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if([manager fileExistsAtPath:ndestFolder] == NO)
|
|
{
|
|
ndestFolder = [ndestFolder stringByAppendingString:@"/"]; // createpath requires a trailing slash
|
|
Platform::createPath([ndestFolder UTF8String]);
|
|
}
|
|
|
|
bool ret = [manager copyPath:nsource toPath:ndest handler:nil];
|
|
|
|
[pool release];
|
|
return ret;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool dFileRename(const char *source, const char *dest)
|
|
{
|
|
if(source == NULL || dest == NULL)
|
|
return false;
|
|
|
|
NSFileManager *manager = [NSFileManager defaultManager];
|
|
|
|
NSString *nsource = [manager stringWithFileSystemRepresentation:source length:dStrlen(source)];
|
|
NSString *ndest = [manager stringWithFileSystemRepresentation:dest length:dStrlen(dest)];
|
|
|
|
if(! [manager fileExistsAtPath:nsource])
|
|
{
|
|
Con::errorf("dFileRename: no file exists at %s",source);
|
|
return false;
|
|
}
|
|
|
|
if( [manager fileExistsAtPath:ndest] )
|
|
{
|
|
Con::warnf("dFileRename: Deleting files at path: %s", dest);
|
|
}
|
|
|
|
bool ret = [manager movePath:nsource toPath:ndest handler:nil];
|
|
|
|
return ret;
|
|
}
|
|
|
|
#pragma mark -
|
|
#pragma mark ---- ShellExecute ----
|
|
class ExecuteThread : public Thread
|
|
{
|
|
const char* zargs;
|
|
const char* directory;
|
|
const char* executable;
|
|
public:
|
|
ExecuteThread(const char *_executable, const char *_args /* = NULL */, const char *_directory /* = NULL */) : Thread(0, NULL, false, true)
|
|
{
|
|
zargs = dStrdup(_args);
|
|
directory = dStrdup(_directory);
|
|
executable = dStrdup(_executable);
|
|
start();
|
|
}
|
|
|
|
virtual void run(void* arg);
|
|
};
|
|
|
|
static char* _unDoubleQuote(char* arg)
|
|
{
|
|
U32 len = dStrlen(arg);
|
|
if(!len)
|
|
return arg;
|
|
|
|
if(arg[0] == '"' && arg[len-1] == '"')
|
|
{
|
|
arg[len - 1] = '\0';
|
|
return arg + 1;
|
|
}
|
|
return arg;
|
|
}
|
|
|
|
void ExecuteThread::run(void* arg)
|
|
{
|
|
// 2k should be enough. if it's not, bail.
|
|
// char buf[2048];
|
|
// U32 len = dSprintf(buf, sizeof(buf), "%s %s -workingDir %s", executable, args, directory);
|
|
// if( len >= sizeof(buf))
|
|
// {
|
|
// Con::errorf("shellExecute(): the command was too long, and won't be run.");
|
|
// return;
|
|
// }
|
|
// // calls sh with the string and blocks until the command returns.
|
|
// system(buf);
|
|
|
|
// FIXME: there is absolutely no error checking in here.
|
|
printf("creating nstask\n");
|
|
NSTask *aTask = [[NSTask alloc] init];
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
|
|
// scan the args list, breaking it up, space delimited, backslash escaped.
|
|
U32 len = dStrlen(zargs);
|
|
char args[len+1];
|
|
dStrncpy(args, zargs, len+1);
|
|
char *lastarg = args;
|
|
bool escaping = false;
|
|
for(int i = 0; i< len; i++)
|
|
{
|
|
char c = args[i];
|
|
// a backslash escapes the next character
|
|
if(escaping)
|
|
continue;
|
|
if(c == '\\')
|
|
escaping = true;
|
|
|
|
if(c == ' ')
|
|
{
|
|
args[i] = '\0';
|
|
if(*lastarg)
|
|
[array addObject:[NSString stringWithUTF8String: _unDoubleQuote(lastarg)]];
|
|
lastarg = args + i + 1;
|
|
}
|
|
}
|
|
if(*lastarg)
|
|
[array addObject:[NSString stringWithUTF8String: _unDoubleQuote(lastarg)]];
|
|
|
|
[aTask setArguments: array];
|
|
|
|
[aTask setCurrentDirectoryPath:[NSString stringWithUTF8String: this->directory]];
|
|
[aTask setLaunchPath:[NSString stringWithUTF8String:executable]];
|
|
[aTask launch];
|
|
[aTask waitUntilExit];
|
|
U32 ret = [aTask terminationStatus];
|
|
Con::executef("onExecuteDone", Con::getIntArg(ret));
|
|
printf("done nstask\n");
|
|
}
|
|
|
|
ConsoleFunction(shellExecute, bool, 2, 4, "(executable, [args], [directory])")
|
|
{
|
|
ExecuteThread *et = new ExecuteThread(argv[1], argc > 2 ? argv[2] : NULL, argc > 3 ? argv[3] : NULL);
|
|
TORQUE_UNUSED(et);
|
|
return true; // Bug: BPNC error: need feedback on whether the command was sucessful
|
|
}
|