Skip to content
This repository has been archived by the owner on Oct 23, 2019. It is now read-only.

Mono/Linux Improvements #25

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions Source/ClassLibrary/DateTime.CLR/DateTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1544,8 +1544,16 @@ public static int MakeTime(int hour, int minute, int second, int month, int day,
default:
PhpException.ArgumentValueNotSupported("daylightSaving", daylightSaving);
break;
}
return DateTimeUtils.UtcToUnixTimeStamp(TimeZoneInfo.ConvertTimeToUtc(local, zone));
}
try
{
return DateTimeUtils.UtcToUnixTimeStamp(TimeZoneInfo.ConvertTimeToUtc(local, zone));
}
catch (Exception e)
{
// IX: Was throwing "System.ArgumentException: dateTime parameter is an invalid time" for mktime(0,0,0,10,10,2010)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is failing for specific input argument, do not try/catch everything, just take care of the input argument (if ... then ...)

return -1;
}
}

#endregion
Expand Down
28 changes: 26 additions & 2 deletions Source/ClassLibrary/FileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1518,8 +1518,32 @@ public static bool Lock(PhpResource handle, int operation, ref int wouldblock)
var fileStream = phpStream.RawStream as FileStream;
if (fileStream == null) return false;

//
if (EnvironmentUtils.IsDotNetFramework)
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
switch ((StreamLockOptions)operation & ~StreamLockOptions.NoBlocking)
{
case StreamLockOptions.Exclusive:
// Exclusive lock
fileStream.Lock(0, Int64.MaxValue);
return true;

/*
* TODO: Implement.
case StreamLockOptions.Shared:
// Shared lock
*/

case StreamLockOptions.Unlock:
// Unlock always succeeds
fileStream.Unlock(0, Int64.MaxValue);
return true;

default:
PhpException.FunctionNotSupported();
return false;
}

} else if (EnvironmentUtils.IsDotNetFramework)
{
return Lock_dotNET(fileStream, (StreamLockOptions)operation);
}
Expand Down
31 changes: 28 additions & 3 deletions Source/ClassLibrary/Process.CLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ private static Process CreateProcessExecutingCommand(ref string command, bool by

Process process = new Process();

// IX: Hide console window when running inside CassiniDev
process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

if (bypass_shell)
{
var match = CommandLineSplitter.Match(command);
Expand All @@ -283,10 +286,33 @@ private static Process CreateProcessExecutingCommand(ref string command, bool by
PhpException.InvalidArgument("command");
return null;
}

process.StartInfo.FileName = match.Groups["filename"].Value;
process.StartInfo.Arguments = match.Groups["arguments"].Value;
}
else if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// TODO: Parse commands surrounded by single and double quotes (['ls' -la] and ["ls" -la]).
// command = command.Trim();
// if (command.Substring(0, 1) == "\"") ...

int i = command.IndexOf(" ");
string bin, args;
if (i >= 0)
{
// "ls -la"
bin = command.Substring(0, i);
args = command.Substring(i + 1);

process.StartInfo.Arguments = args;
}
else
{
// "ls"
bin = command;
}
process.StartInfo.FileName = bin;
}
else
{
process.StartInfo.FileName = (Environment.OSVersion.Platform != PlatformID.Win32Windows) ? "cmd.exe" : "command.com";
Expand Down Expand Up @@ -544,14 +570,13 @@ private static int CloseProcess(Process/*!*/ process)
try
{
process.WaitForExit();
return process.ExitCode; // Throws exception when process has not started.
}
catch (Exception e)
{
PhpException.Throw(PhpError.Warning, LibResources.GetString("error_waiting_for_process_exit", e.Message));
return -1;
}

return process.ExitCode;
}

/// <summary>
Expand Down
18 changes: 15 additions & 3 deletions Source/Core/Configuration.CLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,10 +1170,22 @@ public PathsSection()
try { current_app_dir = (http_context != null) ? http_context.Server.MapPath("/bin") : "."; } // this can throw on Mono
catch (InvalidOperationException) { current_app_dir = "bin"; }

libraries = /*manager =*/ natives = wrappers = typeDefs = new FullPath(current_app_dir);

string dynamic_path = (http_context != null) ? current_app_dir : Path.GetTempPath();
dynamicWrappers = new FullPath(dynamic_path);

if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// Mono + Apache|XSP don't set the working directory, thus new FullPath() converts "bin" to "//bin" (mono 2.10.9) or "/bin".
// It's preferable to build a path relative to the AppDomain BaseDirectory

FullPath basePath = new FullPath(AppDomain.CurrentDomain.BaseDirectory);
libraries = /*manager =*/ natives = wrappers = typeDefs = new FullPath(current_app_dir, basePath);
dynamicWrappers = new FullPath(dynamic_path, basePath);
}
else
{
libraries = /*manager =*/ natives = wrappers = typeDefs = new FullPath(current_app_dir);
dynamicWrappers = new FullPath(dynamic_path);
}
}

/// <summary>
Expand Down
47 changes: 45 additions & 2 deletions Source/Core/Execution.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,51 @@ public static int ShellExec(string command, OutputHandling handling, IList array
}
}

p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + command;
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// TODO: Use same code in ShellExec() and CreateProcessExecutingCommand()
string bin, args;

command = command.Trim();
string quoteChar = "\"";
if (command.Substring(0, 1) == quoteChar)
{
// Parse commands surrounded by single and double quotes (['ls' -la] and ["ls" -la]).
int end = command.IndexOf(quoteChar, 1);
bin = command.Substring(1, end - 1);
args = command.Substring(end + 1);

// TODO: Support redirections.
args = args.Replace("2>&1", "");

p.StartInfo.Arguments = args;
// System.Console.WriteLine("bin: " + bin + ", args: " + args);
}
else
{
int i = command.IndexOf(" ");
if (i >= 0)
{
// "ls -la"
bin = command.Substring(0, i);
args = command.Substring(i + 1);

p.StartInfo.Arguments = args;
}
else
{
// "ls"
bin = command;
}
}
p.StartInfo.FileName = bin;
}
else
{
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + command;
}

p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
p.StartInfo.RedirectStandardOutput = true;
Expand Down
12 changes: 8 additions & 4 deletions Source/Core/PhpStream.CLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,14 @@ public static bool ResolvePath(ref string path, out StreamWrapper wrapper, Check

// Replace all '/' with '\'.
// path = path.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
Debug.Assert(
path.IndexOf(Path.AltDirectorySeparatorChar) == -1 ||
(Path.AltDirectorySeparatorChar == Path.DirectorySeparatorChar), // on Mono, so ignore it
string.Format("'{0}' should not contain '{1}' char.", path, Path.AltDirectorySeparatorChar));

if (Environment.OSVersion.Platform != PlatformID.Unix)
{
Debug.Assert(
path.IndexOf(Path.AltDirectorySeparatorChar) == -1 ||
(Path.AltDirectorySeparatorChar == Path.DirectorySeparatorChar), // on Mono, so ignore it
string.Format("'{0}' should not contain '{1}' char.", path, Path.AltDirectorySeparatorChar));
}

// The file wrapper expects an absolute path w/o the scheme, others expect the scheme://url.
if (scheme != "file")
Expand Down
26 changes: 25 additions & 1 deletion Source/Core/ScriptContext.CLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,23 @@ private void InitConstants(DualDictionary<string, object> _constants)
_constants.Add("PHP_RELEASE_VERSION", PhpVersion.Release, false);
_constants.Add("PHP_VERSION_ID", PhpVersion.Major * 10000 + PhpVersion.Minor * 100 + PhpVersion.Release, false);
_constants.Add("PHP_EXTRA_VERSION", PhpVersion.Extra, false);
_constants.Add("PHP_OS", Environment.OSVersion.Platform == PlatformID.Win32NT ? "WINNT" : "WIN32", false); // TODO: GENERICS (Unix)

string php_os = "Unknown";
switch (Environment.OSVersion.Platform)
{
case PlatformID.Win32NT:
php_os = "WINNT";
break;
case PlatformID.Win32S:
case PlatformID.Win32Windows:
case PlatformID.WinCE:
php_os = "WIN32";
break;
case PlatformID.Unix:
php_os = "Linux";
break;
}
_constants.Add("PHP_OS", php_os, false);
_constants.Add("PHP_SAPI", (System.Web.HttpContext.Current == null) ? "cli" : "isapi", false);
_constants.Add("DIRECTORY_SEPARATOR", FullPath.DirectorySeparatorString, false);
_constants.Add("PATH_SEPARATOR", Path.PathSeparator.ToString(), false);
Expand Down Expand Up @@ -574,6 +590,14 @@ public object DynamicInclude(
DTypeDesc includer,
InclusionTypes inclusionType)
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// Fix for absolute-path-includes on Unix filesystems.
// Example: include_once('/path/app\libs\include.php')
// HACK: Translate "\" to "/"
includerFileRelPath = includerFileRelPath.Replace('\\', '/');
}

ApplicationConfiguration app_config = Configuration.Application;

// determines inclusion behavior:
Expand Down
18 changes: 18 additions & 0 deletions Source/Core/StreamWrappers.CLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,15 @@ private static long ToStatUnixTimeStamp(FileSystemInfo info, Func<FileSystemInfo
/// </summary>
public static FileModeFlags GetFileMode(FileInfo info)
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// Only some flags are currently supported
// TODO: Use info.GetAccessControl()?
FileModeFlags flags = new FileModeFlags();
if (!info.IsReadOnly) flags |= FileModeFlags.Write;
return flags;
}

System.Security.AccessControl.AuthorizationRuleCollection acl;

try
Expand All @@ -281,6 +290,15 @@ public static FileModeFlags GetFileMode(FileInfo info)
/// </summary>
public static FileModeFlags GetFileMode(DirectoryInfo info)
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// Only some flags are currently supported
// TODO: Use info.GetAccessControl()?
FileModeFlags flags = new FileModeFlags();
if ((info.Attributes & FileAttributes.ReadOnly) == 0) flags |= FileModeFlags.Write;
return flags;
}

System.Security.AccessControl.AuthorizationRuleCollection acl;

try
Expand Down
Loading