[runtime] Latest attempt at the cctor abort race. All tests passing locally.
mono/tests/gc-descriptors/Makefile
mono/unit-tests/Makefile
mono/benchmark/Makefile
-mono/io-layer/Makefile
mono/mini/Makefile
mono/profiler/Makefile
m4/Makefile
KEY_FILE = ../../msfinal.pub
SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699 /nowarn:618
-LIB_REFS = System System.Xml System.Xml.Linq System.Runtime.Serialization System.Core System.Numerics System.Net.Http \
+LIB_REFS = System System.Xml System.Xml.Linq System.Runtime.Serialization System.Core System.Numerics System.Net.Http System.Transactions \
System.IO.Compression System.Data System.ComponentModel.Composition System.IO.Compression.FileSystem \
Facades/System.Security.Cryptography.Algorithms
ifeq (2.1, $(FRAMEWORK_VERSION))
LIB_REFS += System.Web.Services
+else
+LIB_REFS += System.Web System.Drawing
endif
LIB_MCS_FLAGS = $(SIGN_FLAGS)
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.AppDomainUnloadedException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ApplicationException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ApplicationId))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ArgIterator))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ArgumentException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ArgumentNullException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ArgumentOutOfRangeException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.RankException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ResolveEventArgs))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.ResolveEventHandler))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.RuntimeArgumentHandle))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.RuntimeFieldHandle))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.RuntimeMethodHandle))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.RuntimeTypeHandle))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Type))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.TypeAccessException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.TypeCode))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.TypedReference))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.TypeInitializationException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.TypeLoadException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.TypeUnloadedException))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.ServicePointManager))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.SocketAddress))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.TransportContext))]
-[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.TransportType))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.UploadDataCompletedEventArgs))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.UploadDataCompletedEventHandler))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Net.UploadFileCompletedEventArgs))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Timers.ElapsedEventHandler))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Timers.Timer))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Timers.TimersDescriptionAttribute))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.CommittableTransaction))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.DependentCloneOption))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.DependentTransaction))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.Enlistment))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.EnlistmentOptions))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.EnterpriseServicesInteropOption))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.HostCurrentTransactionCallback))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.IDtcTransaction))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.IEnlistmentNotification))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.IPromotableSinglePhaseNotification))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.ISimpleTransactionSuperior))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.ISinglePhaseNotification))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.IsolationLevel))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.ITransactionPromoter))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.PreparingEnlistment))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.SinglePhaseEnlistment))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.SubordinateTransaction))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.Transaction))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionAbortedException))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionCompletedEventHandler))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionEventArgs))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionException))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionInDoubtException))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionInformation))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionInterop))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionManager))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionManagerCommunicationException))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionOptions))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionPromotionException))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionScope))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionScopeAsyncFlowOption))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionScopeOption))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionStartedEventHandler))]
+[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Transactions.TransactionStatus))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Web.HttpUtility))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Windows.Input.ICommand))]
[assembly:System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Xml.ConformanceLevel))]
namespace System.Transactions
{
public delegate Transaction HostCurrentTransactionCallback ();
- public delegate void TransactionCompletedEventHandler (object o,
+ public delegate void TransactionCompletedEventHandler (object sender,
TransactionEventArgs e);
- public delegate void TransactionStartedEventHandler (object o,
+ public delegate void TransactionStartedEventHandler (object sender,
TransactionEventArgs e);
}
return true;
}
+ public void SetDistributedTransactionIdentifier (IPromotableSinglePhaseNotification promotableNotification, Guid distributedTransactionIdentifier)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool EnlistPromotableSinglePhase (IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public byte[] GetPromotedToken ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public Guid PromoterType
+ {
+ get { throw new NotImplementedException (); }
+ }
+
[MonoTODO ("EnlistmentOptions being ignored")]
public Enlistment EnlistVolatile (
IEnlistmentNotification notification,
[Serializable]
public class TransactionException : SystemException
{
- protected TransactionException ()
+ public TransactionException ()
{
}
[Serializable]
public class TransactionInDoubtException : TransactionException
{
- protected TransactionInDoubtException ()
+ public TransactionInDoubtException ()
{
}
[MonoTODO]
public static class TransactionInterop
{
+ public static readonly Guid PromoterTypeDtc = new Guid ("14229753-FFE1-428D-82B7-DF73045CB8DA");
+
[MonoTODO]
public static IDtcTransaction GetDtcTransaction (Transaction transaction)
{
[Serializable]
public class TransactionManagerCommunicationException : TransactionException
{
- protected TransactionManagerCommunicationException ()
+ public TransactionManagerCommunicationException ()
{
}
[Serializable]
public class TransactionPromotionException : TransactionException
{
- protected TransactionPromotionException ()
+ public TransactionPromotionException ()
{
}
TransactionManager.DefaultTimeout, TransactionScopeAsyncFlowOption.Suppress);
}
+ public TransactionScope (Transaction transactionToUse,
+ TransactionScopeAsyncFlowOption asyncFlowOption)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public TransactionScope (Transaction transactionToUse,
+ TimeSpan scopeTimeout,
+ TransactionScopeAsyncFlowOption asyncFlowOption)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public TransactionScope (TransactionScopeOption scopeOption,
+ TransactionOptions transactionOptions,
+ TransactionScopeAsyncFlowOption asyncFlowOption)
+ {
+ throw new NotImplementedException ();
+ }
+
void Initialize (TransactionScopeOption scopeOption,
Transaction tx, TransactionOptions options,
DTCOption interop, TimeSpan timeout, TransactionScopeAsyncFlowOption asyncFlow)
public void CreateEvidenceForUrl_Basic ()
{
Evidence e = XmlSecureResolver.CreateEvidenceForUrl (null);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
Assert.AreEqual (0, e.Count, "null");
#else
Assert.IsNull (e);
#endif
e = XmlSecureResolver.CreateEvidenceForUrl (String.Empty);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
Assert.AreEqual (0, e.Count, "String.Empty");
#else
Assert.IsNull (e);
}
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// and you must have discovery access to the combined path
// note: the cache behaviour is tested in the CAS tests
if (SecurityManager.SecurityEnabled) {
public string FileName {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (SecurityManager.SecurityEnabled) {
new FileIOPermission (FileIOPermissionAccess.PathDiscovery, filename).Demand ();
}
public static FileVersionInfo GetVersionInfo (string fileName)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (SecurityManager.SecurityEnabled) {
new FileIOPermission (FileIOPermissionAccess.Read, fileName).Demand ();
}
public partial class AppDomain
{
- internal String GetTargetFrameworkName()
- {
- return ".NETFramework,Version=v4.5";
- }
-
internal static bool IsAppXModel ()
{
return false;
public virtual string GetFileName()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (SecurityManager.SecurityEnabled && (fileName != null) && (fileName.Length > 0)) {
string fn = Path.GetFullPath (fileName);
new FileIOPermission (FileIOPermissionAccess.PathDiscovery, fn).Demand ();
// The above is an internal value used by Path.GetTempFile to
// get a file with 600 permissions, regardless of the umask
// settings. If a value "1" must be introduced here, update
- // both metadata/file-io.c and Path.GetTempFile
+ // both metadata/w32file.c and Path.GetTempFile
//
}
}
if (!suppressSecurityChecks)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#pragma warning disable 618
new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
#pragma warning restore 618
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
public abstract IPermission Copy ();
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#endif
public void Demand ()
{
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
}
#if MOBILE
- [Conditional ("FEATURE_MONO_CAS")]
+ [Conditional ("MONO_FEATURE_CAS")]
#else
[MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
#endif
/// </summary>
public static string GetEnvironmentVariable (string variable)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (SecurityManager.SecurityEnabled) {
new EnvironmentPermission (EnvironmentPermissionAccess.Read, variable).Demand ();
}
else
dir = UnixGetFolderPath (folder, option);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) {
new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand ();
}
// (C) 2004 Motus Technologies Inc. (http://www.motus.com)
//
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
using NUnit.Framework;
using System;
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
using System;
using System.Security;
}
}
-#endif
\ No newline at end of file
+#endif
/// </devdoc>
internal static class SecurityUtils {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
private static volatile ReflectionPermission memberAccessPermission = null;
private static volatile ReflectionPermission restrictedMemberAccessPermission = null;
#endif
private static void DemandReflectionAccess(Type type) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
try {
MemberAccessPermission.Demand();
}
[SecuritySafeCritical]
private static void DemandGrantSet(Assembly assembly) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet targetGrantSet = assembly.PermissionSet;
targetGrantSet.AddPermission(RestrictedMemberAccessPermission);
targetGrantSet.Demand();
}
private static bool HasReflectionPermission(Type type) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
try {
DemandReflectionAccess(type);
return true;
// The World of Compile
//
internal void Compile(NavigatorInput input, XmlResolver xmlResolver, Evidence evidence) {
-#if !FEATURE_MONO_CAS
+#if !MONO_FEATURE_CAS
evidence = null;
#endif
Debug.Assert(input != null);
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
static internal Stream GetFileStream(string filename) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
(new FileIOPermission(FileIOPermissionAccess.Read, filename)).Assert();
try {
return new FileStream(filename,FileMode.Open,FileAccess.Read,FileShare.Read);
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
static internal FileVersionInfo GetVersionInfo(string filename) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
(new FileIOPermission(FileIOPermissionAccess.Read, filename)).Assert(); // MDAC 62038
try {
return FileVersionInfo.GetVersionInfo(filename); // MDAC 60411
internal class XMLSchema {
internal static TypeConverter GetConverter(Type type) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
HostProtectionAttribute protAttrib = new HostProtectionAttribute();
protAttrib.SharedState = true;
CodeAccessPermission permission = (CodeAccessPermission)protAttrib.CreatePermission();
return TypeDescriptor.GetConverter(type);
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
internal bool RequiresMemberAccessForWrite(SecurityException securityException)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
EnsureMethodsImported();
if (!IsTypeVisible(UnderlyingType))
}
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[Fx.Tag.SecurityNote(Critical = "Holds instance of SecurityPermission that we will Demand for SerializationFormatter."
+ " Should not be modified to something else.")]
[SecurityCritical]
[SecuritySafeCritical]
public void DemandSerializationFormatterPermission()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (!demandedSerializationFormatterPermission)
{
Globals.SerializationFormatterPermission.Demand();
[SecuritySafeCritical]
public void DemandMemberAccessPermission()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (!demandedMemberAccessPermission)
{
Globals.MemberAccessPermission.Demand();
[MethodImpl(MethodImplOptions.NoInlining)]
internal void GetObjectData(ISerializable obj, SerializationInfo serInfo, StreamingContext context)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// Demand the serialization formatter permission every time
Globals.SerializationFormatterPermission.Demand();
#endif
[SecurityCritical]
internal static bool IsInFullTrust()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (!SecurityManager.CurrentThreadRequiresSecurityContextCapture())
{
return true;
[SecurityCritical]
internal static bool CheckAppDomainPermissions(PermissionSet permissions)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
return AppDomain.CurrentDomain.IsHomogenous &&
permissions.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet);
#else
[SecurityCritical]
internal static bool HasEtwPermissions()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
//Currently unrestricted permissions are required to create Etw provider.
PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
return CheckAppDomainPermissions(permissions);
[SecuritySafeCritical]
get
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (!checkedForFullTrust)
{
inFullTrust = AppDomain.CurrentDomain.IsFullyTrusted;
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
public partial class XmlSecureResolver : XmlResolver {
XmlResolver resolver;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet permissionSet;
#endif
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
public XmlSecureResolver(XmlResolver resolver, string securityUrl) : this(resolver, CreateEvidenceForUrl(securityUrl)) {}
public XmlSecureResolver(XmlResolver resolver, Evidence evidence) : this(resolver, SecurityManager.GetStandardSandbox(evidence)) {}
public XmlSecureResolver(XmlResolver resolver, PermissionSet permissionSet) {
this.resolver = resolver;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
this.permissionSet = permissionSet;
#endif
}
}
public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
permissionSet.PermitOnly();
#endif
return resolver.GetEntity(absoluteUri, role, ofObjectToReturn);
}
public static Evidence CreateEvidenceForUrl(string securityUrl) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
Evidence evidence = new Evidence();
if (securityUrl != null && securityUrl.Length > 0) {
evidence.AddHostEvidence(new Url(securityUrl));
#endif
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[Serializable]
private class UncDirectory : EvidenceBase, IIdentityPermissionFactory {
private string uncDir;
[PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
public partial class XmlSecureResolver : XmlResolver {
public override Task<object> GetEntityAsync(Uri absoluteUri, string role, Type ofObjectToReturn) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
permissionSet.PermitOnly();
#endif
return resolver.GetEntityAsync(absoluteUri, role, ofObjectToReturn);
if (stylesheet == null) {
throw new ArgumentNullException("stylesheet");
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (evidence == null) {
evidence = new Evidence();
}
else {
args = new Type[] {receiverType};
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
IntSecurity.FullReflection.Assert();
#endif
try {
else {
args = new Type[] {receiverType};
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
IntSecurity.FullReflection.Assert();
#endif
try {
/// a single object to be re-used for more than one type.
/// </devdoc>
private object CreateInstance(Type type) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if ((!(type.IsPublic || type.IsNestedPublic)) && (type.Assembly == typeof(DebugTypeDescriptor).Assembly)) {
IntSecurity.FullReflection.Demand();
}
[HostProtection(SharedState = true)]
internal static class IntSecurity {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
public static readonly CodeAccessPermission UnmanagedCode = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
public static readonly CodeAccessPermission FullReflection = new ReflectionPermission(PermissionState.Unrestricted);
#endif
public static string UnsafeGetFullPath(string fileName) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
string full = fileName;
FileIOPermission fiop = new FileIOPermission(PermissionState.None);
else {
args = new Type[] {receiverType};
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
IntSecurity.FullReflection.Assert();
try {
#endif
resetMethod = FindMethod(componentClass, "Reset" + Name, args, typeof(void), /* publicOnly= */ false);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
}
finally {
CodeAccessPermission.RevertAssert();
args = new Type[] {receiverType};
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
IntSecurity.FullReflection.Assert();
try {
#endif
shouldSerializeMethod = FindMethod(componentClass, "ShouldSerialize" + Name,
args, typeof(Boolean), /* publicOnly= */ false);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
}
finally {
CodeAccessPermission.RevertAssert();
Type converterType = GetTypeFromName(instanceAttr.ConverterTypeName);
if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType))
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
try {
IntSecurity.FullReflection.Assert();
#endif
return (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
} finally {
CodeAccessPermission.RevertAssert();
}
Type converterType = GetTypeFromName(typeAttr.ConverterTypeName);
if (converterType != null && typeof(TypeConverter).IsAssignableFrom(converterType))
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
try {
IntSecurity.FullReflection.Assert();
#endif
_converter = (TypeConverter)ReflectTypeDescriptionProvider.CreateInstance(converterType, _type);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
} finally {
CodeAccessPermission.RevertAssert();
}
{
throw new ArgumentNullException("type");
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet typeDescriptorPermission = new PermissionSet(PermissionState.None);
typeDescriptorPermission.AddPermission(new TypeDescriptorPermission(TypeDescriptorPermissionFlags.RestrictedRegistrationAccess));
{
throw new ArgumentNullException("instance");
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
Type type = instance.GetType();
PermissionSet typeDescriptorPermission = new PermissionSet(PermissionState.None);
// sense that they provide a public API while not necessarily being public themselves. As such,
// we need to allow instantiation of internal TypeDescriptionProviders. See the thread attached
// to VSWhidbey #500522 for a more detailed discussion.
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
IntSecurity.FullReflection.Assert();
try {
#endif
prov = (TypeDescriptionProvider)Activator.CreateInstance(providerType);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
}
finally {
CodeAccessPermission.RevertAssert();
{
throw new ArgumentNullException("type");
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet typeDescriptorPermission = new PermissionSet(PermissionState.None);
typeDescriptorPermission.AddPermission(new TypeDescriptorPermission(TypeDescriptorPermissionFlags.RestrictedRegistrationAccess));
{
throw new ArgumentNullException("instance");
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
Type type = instance.GetType();
PermissionSet typeDescriptorPermission = new PermissionSet(PermissionState.None);
}
protected Win32Exception(SerializationInfo info, StreamingContext context) : base (info, context) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
IntSecurity.UnmanagedCode.Demand();
#endif
nativeErrorCode = info.GetInt32("NativeErrorCode");
Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"rawfile: " + rawFile);
string codeBase;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// FileIOPermission is required for ApplicationBase in URL-hosted domains
FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
perm.Assert();
// file://fullpath/foo.exe
//
string fileName;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
perm.Assert();
try
else if(!resourceAssembly.IsDynamic) { // EscapedCodeBase won't be supported by emitted assemblies anyway
Debug.WriteLineIf(RuntimeLicenseContextSwitch.TraceVerbose,"resourceAssembly is not null");
string fileName;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
FileIOPermission perm = new FileIOPermission(PermissionState.Unrestricted);
perm.Assert();
#endif
}
finally
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
static Stream OpenRead(Uri resourceUri) {
Stream result = null;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet perms = new PermissionSet(PermissionState.Unrestricted);
perms.Assert();
catch (Exception e) {
Debug.Fail(e.ToString());
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
finally {
CodeAccessPermission.RevertAssert();
}
public static TraceListenerCollection Listeners {
[HostProtection(SharedState=true)]
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// Do a full damand
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#endif
/// </devdoc>
[System.Diagnostics.Conditional("TRACE")]
public static void Close() {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// Do a full damand
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#endif
get {
if (stackTrace == null)
stackTrace = Environment.StackTrace;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
else
new EnvironmentPermission(PermissionState.Unrestricted).Demand();
#endif
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
private static void InitProcessInfo() {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// Demand unmanaged code permission
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#endif
internal static string AppName {
get {
if (appName == null) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Assert();
#endif
appName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
}
private static void DemandReflectionAccess(Type type) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
try {
MemberAccessPermission.Demand();
}
[SecuritySafeCritical]
private static void DemandGrantSet(Assembly assembly) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet targetGrantSet = assembly.PermissionSet;
targetGrantSet.AddPermission(RestrictedMemberAccessPermission);
targetGrantSet.Demand();
set
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.ControlPolicyPermission.Demand();
#endif
Instance.CredentialPolicy = value;
/// </devdoc>
public static void Register(IAuthenticationModule authenticationModule)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.UnmanagedPermission.Demand();
#endif
Instance.Register(authenticationModule);
/// </devdoc>
public static void Unregister(IAuthenticationModule authenticationModule)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.UnmanagedPermission.Demand();
#endif
Instance.Unregister(authenticationModule);
/// </devdoc>
public static void Unregister(string authenticationScheme)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.UnmanagedPermission.Demand();
#endif
Instance.Unregister(authenticationScheme);
get {
//This check will not allow to use local user credentials at will.
//Hence the username will not be exposed to the network
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new EnvironmentPermission(EnvironmentPermissionAccess.Read, "USERNAME").Demand();
#endif
return SystemNetworkCredential.defaultCredential;
get {
//This check will not allow to use local user credentials at will.
//Hence the username will not be exposed to the network
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new EnvironmentPermission(EnvironmentPermissionAccess.Read, "USERNAME").Demand();
#endif
return SystemNetworkCredential.defaultCredential;
private static void DemandCallback(object state)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
((CodeAccessPermission) state).Demand();
#endif
}
internal static class ExceptionHelper
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
internal static readonly KeyContainerPermission KeyContainerPermissionOpen = new KeyContainerPermission(KeyContainerPermissionFlags.Open);
internal static readonly WebPermission WebPermissionUnrestricted = new WebPermission(NetworkAccess.Connect);
internal static readonly SecurityPermission UnmanagedPermission = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode);
/// </devdoc>
public class NetworkCredential : ICredentials,ICredentialsByHost {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
private static volatile EnvironmentPermission m_environmentUserNamePermission;
private static volatile EnvironmentPermission m_environmentDomainNamePermission;
private static readonly object lockingObject = new object();
}
#endif //!FEATURE_PAL
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
void InitializePart1() {
if (m_environmentUserNamePermission == null) {
lock(lockingObject) {
/// </devdoc>
public string UserName {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
InitializePart1();
m_environmentUserNamePermission.Demand();
#endif
/// </devdoc>
public string Password {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.UnmanagedPermission.Demand();
#endif
return InternalGetPassword();
/// </devdoc>
public SecureString SecurePassword {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.UnmanagedPermission.Demand();
#endif
return InternalGetSecurePassword().Copy();
/// </devdoc>
public string Domain {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
InitializePart1();
m_environmentDomainNamePermission.Demand();
#endif
{
/// Returns objects that describe the network interfaces on the local computer.
public static NetworkInterface[] GetAllNetworkInterfaces(){
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
(new NetworkInformationPermission(NetworkInformationAccess.Read)).Demand();
#endif
return SystemNetworkInterface.GetNetworkInterfaces();
return m_BindIPEndPointDelegate;
}
set {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.InfrastructurePermission.Demand();
#endif
m_BindIPEndPointDelegate = value;
throw new NotSupportedException(SR.GetString(SR.net_servicePointAddressNotSupportedInHostMode));
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// Don't let low-trust apps discover the proxy information.
if (m_ProxyServicePoint)
{
throw new ArgumentNullException("creator");
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return RequestCacheManager.GetBinding(string.Empty).Policy;
}
set {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// This is a replacement of RequestCachePermission demand since we are not including the latest in the product.
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
{
get
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return InternalDefaultWebProxy;
set
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
InternalDefaultWebProxy = value;
//
public static IWebProxy GetSystemWebProxy()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return InternalGetSystemWebProxy();
// demand the same permissions, then we should remove our
// demand here.
//
- #if FEATURE_MONO_CAS
+ #if MONO_FEATURE_CAS
ExceptionHelper.KeyContainerPermissionOpen.Demand();
#endif
// For v 1.1 compat We want to ensure the store is opened under the **process** acount.
//
try {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
using (WindowsIdentity.Impersonate(IntPtr.Zero))
#endif
{
// Note: We call a user certificate selection delegate under permission
// assert but the signature of the delegate is unique so it's safe
//
- #if FEATURE_MONO_CAS
+ #if MONO_FEATURE_CAS
[StorePermission(SecurityAction.Assert, Unrestricted=true)]
#endif
private bool AcquireClientCredentials(ref byte[] thumbPrint)
// Note: We call a user certificate selection delegate under permission
// assert but the signature of the delegate is unique so it's safe
//
- #if FEATURE_MONO_CAS
+ #if MONO_FEATURE_CAS
[StorePermission(SecurityAction.Assert, Unrestricted=true)]
#endif
private bool AcquireServerCredentials(ref byte[] thumbPrint)
//
// For v 1.1 compat We want to ensure the credential are accessed under >>process<< acount.
//
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
using (WindowsIdentity.Impersonate(IntPtr.Zero))
#endif
{
//SECURITY: The scenario is allowed in semitrust StorePermission is asserted for Chain.Build
// A user callback has unique signature so it is safe to call it under permisison assert.
//
- #if FEATURE_MONO_CAS
+ #if MONO_FEATURE_CAS
[StorePermission(SecurityAction.Assert, Unrestricted=true)]
#endif
internal bool VerifyRemoteCertificate(RemoteCertValidationCallback remoteCertValidationCallback)
//
public override int Count {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return m_SyncTable.Count;
//
public override ICollection Keys {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return m_SyncTable.Keys;
public override object SyncRoot {
[HostProtection(Synchronization=true)]
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return m_SyncTable;
//
public override ICollection Values {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
if (m_ValuesWrapper == null)
}
//
public override void Clear() {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
m_SyncTable.Clear();
}
//
public override bool ContainsValue(string value) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
foreach (SpnToken spnToken in m_SyncTable.Values)
// We have to unwrap the SpnKey and just expose the Spn
public override void CopyTo(Array array, int index) {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
CheckCopyToArguments(array, index, Count);
}
//
public override IEnumerator GetEnumerator() {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
try {
Uri uri = new Uri(key);
key = uri.GetParts(UriComponents.Scheme | UriComponents.Host | UriComponents.Port | UriComponents.Path, UriFormat.SafeUnescaped);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new WebPermission(NetworkAccess.Connect, new Uri(key)).Demand();
#endif
}
/// </devdoc>
public IWebProxy Proxy {
get {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
if (!m_ProxySet) {
}
}
set {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
m_Proxy = value;
/// </devdoc>
[Obsolete("This method has been deprecated. Please use the proxy selected for you by default. http://go.microsoft.com/fwlink/?linkid=14202")]
public static WebProxy GetDefaultProxy() {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
return new WebProxy(true);
if (useRegistry) {
// just make the proxy advanced, don't populate with any settings
// note - this will happen in the context of the user performing the deserialization (their proxy settings get read)
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.WebPermissionUnrestricted.Demand();
#endif
UnsafeUpdateFromRegistry();
//
public static void Register(UriParser uriParser, string schemeName, int defaultPort)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ExceptionHelper.InfrastructurePermission.Demand();
#endif
if (uriParser == null)
* This method is internal virtual so the jit does not inline it.
*/
[
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
HostProtection(MayLeakOnAbort=true),
#endif
MethodImplAttribute(MethodImplOptions.NoInlining)
#if !(SILVERLIGHT || FULL_AOT_RUNTIME)
/// <devdoc>
/// </devdoc>
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[HostProtection(MayLeakOnAbort=true)]
#endif
[ResourceExposure(ResourceScope.Machine)] // The AssemblyName is interesting.
/// <devdoc>
/// </devdoc>
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[HostProtection(MayLeakOnAbort=true)]
#endif
[ResourceExposure(ResourceScope.Machine)] // The AssemblyName is interesting.
CompileToAssemblyInternal(regexinfos, assemblyname, attributes, null);
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[HostProtection(MayLeakOnAbort=true)]
#endif
[ResourceExposure(ResourceScope.Machine)]
// <SECREVIEW> Regex only generates string manipulation, so this is ok.
// </SECREVIEW>
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new ReflectionPermission(PermissionState.Unrestricted).Assert();
#endif
try {
#endif
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
// <SECREVIEW> Regex only generates string manipulation, so this is ok.
// </SECREVIEW>
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new ReflectionPermission(PermissionState.Unrestricted).Assert();
#endif
try {
factory = c.FactoryInstanceFromCode(code, options);
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
Type factory;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new ReflectionPermission(PermissionState.Unrestricted).Assert();
#endif
try {
c.GenerateRegexType(pattern, options, fullname, regexes[i].IsPublic, code, tree, factory, mTimeout);
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
// SECREVIEW : Regex only generates string manipulation, so this is
// : ok.
//
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new ReflectionPermission(PermissionState.Unrestricted).Assert();
#endif
try {
CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, new object[0]);
assemblyAttributes.Add(transparencyAttribute);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) });
CustomAttributeBuilder securityRulesAttribute =
new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level2 });
}
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
/// multiple threads.</para>
/// </devdoc>
#if !SILVERLIGHT
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[HostProtection(Synchronization=true)]
#endif
static public Group Synchronized(Group inner) {
/// </devdoc>
#if !SILVERLIGHT
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
[HostProtection(Synchronization=true)]
#endif
static public Match Synchronized(Match inner) {
protected internal override RegexRunner CreateInstance() {
CompiledRegexRunner runner = new CompiledRegexRunner();
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new ReflectionPermission(PermissionState.Unrestricted).Assert();
#endif
runner.SetDelegates((NoParamDelegate) goMethod.CreateDelegate(typeof(NoParamDelegate)),
[System.Security.SecurityCritical] // auto-generated
internal virtual String InternalToString()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
try
{
#pragma warning disable 618
bool safeToReturn = false;
try {
if (!isInvalidPath) {
-#if !FEATURE_CORECLR && FEATURE_MONO_CAS
+#if !FEATURE_CORECLR && MONO_FEATURE_CAS
FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, path, false, false);
#endif
safeToReturn = true;
[System.Security.SecurityCritical] // auto-generated
private FileInfo(SerializationInfo info, StreamingContext context) : base(info, context)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if !FEATURE_CORECLR
FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, FullPath, false, false);
#endif
String directoryName = Path.GetDirectoryName(FullPath);
if (directoryName != null)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, DisplayPath, FullPath);
state.EnsureState();
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public override void Delete()
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, DisplayPath, FullPath);
state.EnsureState();
// Do a demand on the combined path so that we can fail early in case of deny
demandPaths[1] = Directory.GetDemandDir(normalizedSearchPath, true);
_checkHost = checkHost;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
if (checkHost)
{
// For filters like foo\*.cs we need to verify if the directory foo is not denied access.
// Do a demand on the combined path so that we can fail early in case of deny
demandPaths[1] = Directory.GetDemandDir(normalizedSearchPath, true);
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
if (checkHost)
{
[System.Security.SecurityCritical]
internal void DoDemand(String fullPathToDemand)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
if(_checkHost) {
String demandDir = Directory.GetDemandDir(fullPathToDemand, true);
internal override FileInfo CreateObject(SearchResult result)
{
String name = result.FullPath;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name);
state.EnsureState();
String name = result.FullPath;
String permissionName = name + "\\.";
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName);
state.EnsureState();
String name = result.FullPath;
String permissionName = name + "\\.";
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName);
state.EnsureState();
Contract.Assert(isFile);
String name = result.FullPath;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, name);
state.EnsureState();
using System;
using System.Collections;
using System.Security;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
using System.Security.Permissions;
#endif
using Microsoft.Win32;
namespace System.IO {
[Serializable]
-#if !FEATURE_CORECLR && FEATURE_MONO_CAS
+#if !FEATURE_CORECLR && MONO_FEATURE_CAS
[FileIOPermissionAttribute(SecurityAction.InheritanceDemand,Unrestricted=true)]
#endif
[ComVisible(true)]
demandDir = Directory.GetDemandDir(FullPath, true);
else
demandDir = FullPath;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if FEATURE_CORECLR
FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir);
sourceState.EnsureState();
demandDir = Directory.GetDemandDir(FullPath, true);
else
demandDir = FullPath;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if !FEATURE_CORECLR
FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandDir);
#endif
[System.Security.SecuritySafeCritical]
#endif
set {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if !FEATURE_CORECLR
FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, FullPath);
#endif
[ComVisible(false)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
#if !FEATURE_CORECLR
FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, FullPath);
#endif
if (_isOpen) {
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice"));
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (!skipSecurityCheck) {
#pragma warning disable 618
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
if (_isOpen)
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice"));
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (!skipSecurityCheck)
#pragma warning disable 618
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
// Don't use Assembly manifest, but grovel on disk for a file.
try
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new System.Security.Permissions.FileIOPermission(System.Security.Permissions.PermissionState.Unrestricted).Assert();
#endif
}
finally
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
System.Security.CodeAccessPermission.RevertAssert();
#endif
}
// write to the temp directory (enforced via a Windows ACL). Fall back to a MemoryStream.
Stream dataSection = null; // Either a FileStream or a MemoryStream
String tempFile = null;
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet permSet = new PermissionSet(PermissionState.None);
permSet.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted));
permSet.AddPermission(new FileIOPermission(PermissionState.Unrestricted));
#endif
try {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
permSet.Assert();
#endif
tempFile = Path.GetTempFileName();
dataSection = new MemoryStream();
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
PermissionSet.RevertAssert();
#endif
}
throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName));
}
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// If we're creating a delegate, we're about to call a
// constructor taking an integer to represent a target
// method. Since this is very difficult (and expensive)
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
#endif // FEATURE_CORECLR
}
-#endif // FEATURE_MONO_CAS
+#endif // MONO_FEATURE_CAS
if (invokeMethod.GetParametersNoCopy().Length == 0)
{
if (args.Length != 0)
return null;
#endif
String dir = GetRuntimeDirectoryImpl();
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dir).Demand();
#endif
return dir;
String path = sb.ToString();
#endif
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// Do security check
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
#endif
private BinaryMethodReturn binaryMethodReturn;
private bool bIsCrossAppDomain;
#endif
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
private static FileIOPermission sfileIOPermission = new FileIOPermission(PermissionState.Unrestricted);
#endif
private SerStack ValueFixupStack
if (bSimpleAssembly)
{
try {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
sfileIOPermission.Assert();
#endif
try {
#endif // FEATURE_FUSION
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
else {
try
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
sfileIOPermission.Assert();
#endif
try {
assm = Assembly.Load(assemblyName);
}
finally {
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
CodeAccessPermission.RevertAssert();
#endif
}
if ( !FormatterServices.UnsafeTypeForwardersIsEnabled() && sourceAssembly != destAssembly )
{
// we have a type forward to attribute !
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// we can try to see if the dest assembly has less permissionSet
if (!destAssembly.PermissionSet.IsSubsetOf(sourceAssembly.PermissionSet))
#endif
typeFowardedFromAssembly = Assembly.Load(typeInfo.AssemblyString);
}
catch { }
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
if (typeFowardedFromAssembly != sourceAssembly)
{
// throw security exception
}
else
{
-#if FEATURE_MONO_CAS
+#if MONO_FEATURE_CAS
// throw security exception
throw new SecurityException() { Demanded = sourceAssembly.PermissionSet };
#endif
endif
if CROSS_COMPILING
-SUBDIRS = $(btls_dirs) arch utils io-layer cil metadata $(sgen_dirs) mini dis profiler
+SUBDIRS = $(btls_dirs) arch utils cil metadata $(sgen_dirs) mini dis profiler
else
if INSTALL_MONOTOUCH
-SUBDIRS = $(btls_dirs) arch utils io-layer metadata $(sgen_dirs) mini profiler
+SUBDIRS = $(btls_dirs) arch utils metadata $(sgen_dirs) mini profiler
monotouch-do-build:
@list='$(SUBDIRS)'; for subdir in $$list; do \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$target); \
done;
else
-SUBDIRS = $(btls_dirs) arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler
+SUBDIRS = $(btls_dirs) arch utils cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler
endif
endif
-DIST_SUBDIRS = btls arch utils io-layer cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler
+DIST_SUBDIRS = btls arch utils cil metadata $(sgen_dirs) mini dis tests unit-tests benchmark profiler
message (WARNING "SET ARCH: ${BTLS_ARCH}")
set (CMAKE_SYSTEM_PROCESSOR "${BTLS_ARCH}")
endif ()
-if (BUILD_DYNAMIC_BTLS)
-set (C_CXX_FLAGS "-Wall -Wsign-compare -Wmissing-field-initializers -fPIC -ggdb -fvisibility=hidden")
-elseif (BUILD_SHARED_LIBS)
+
set (C_CXX_FLAGS "-Wall -Wsign-compare -Wmissing-field-initializers -fPIC -ggdb -fvisibility=hidden")
-else ()
-set (C_CXX_FLAGS "-Wall -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
-endif()
+
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} ${BTLS_CFLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CXX_FLAGS} ${BTLS_CFLAGS}")
set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${BTLS_CFLAGS}")
${BORINGSSL_OBJECTS}
)
-if (BUILD_SHARED_LIBS)
- add_library (mono-btls-shared SHARED ${MONO_BTLS_SOURCES})
-else ()
- add_library (mono-btls-static STATIC ${MONO_BTLS_SOURCES})
-endif ()
+add_library (mono-btls-shared SHARED ${MONO_BTLS_SOURCES})
-EXTRA_DIST = \
+MONO_BTLS_SOURCES_FILES = \
btls-bio.c \
btls-bio.h \
btls-error.c \
btls-x509-verify-param.h \
CMakeLists.txt
+EXTRA_DIST = $(MONO_BTLS_SOURCES_FILES)
+
CMAKE_VERBOSE=$(if $(V),VERBOSE=1,)
CMAKE_ARGS = -D CMAKE_INSTALL_PREFIX:PATH=$(prefix) -D BTLS_ROOT:PATH=$(BTLS_ROOT) \
-D SRC_DIR:PATH=$(abs_top_srcdir)/mono/btls -D BTLS_CFLAGS:STRING="$(BTLS_CFLAGS)"
-all-local: build-shared/libmono-btls-shared$(libsuffix) build-static/libmono-btls-static.a
+all-local: build-shared/libmono-btls-shared$(libsuffix)
build-shared/Makefile:
-mkdir -p build-shared
(cd build-shared && CC="$(CC)" CXX="$(CXX)" $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) -DBUILD_SHARED_LIBS=1 $(abs_top_srcdir)/mono/btls)
-build-shared/libmono-btls-shared$(libsuffix): build-shared/Makefile
+build-shared/libmono-btls-shared$(libsuffix): build-shared/Makefile $(MONO_BTLS_SOURCES_FILES)
$(MAKE) -C build-shared $(CMAKE_VERBOSE)
-build-static/Makefile:
- -mkdir -p build-static
- (cd build-static && CC="$(CC)" CXX="$(CXX)" $(CMAKE) $(CMAKE_ARGS) $(BTLS_CMAKE_ARGS) $(abs_top_srcdir)/mono/btls)
-
-build-static/libmono-btls-static.a: build-static/Makefile
- $(MAKE) -C build-static $(CMAKE_VERBOSE)
-
clean-local:
- -rm -rf build-static
-rm -rf build-shared
install-exec-local:
runtime_lib= \
$(metadata_lib) \
$(gc_lib) \
- $(top_builddir)/mono/io-layer/libwapi.la \
$(top_builddir)/mono/utils/libmonoutils.la \
$(GLIB_LIBS) $(LIBICONV)
+++ /dev/null
-/semantic.cache
-/.deps
-/.libs
-/Makefile
-/Makefile.in
-/mono-handle-d
-/*.lo
-/*.la
-/*.o
-/.project
-/.cproject
-/TAGS
+++ /dev/null
-
-noinst_LTLIBRARIES = libwapi.la
-
-AM_CPPFLAGS = \
- $(GLIB_CFLAGS) \
- $(LIBGC_CPPFLAGS) \
- -DMONO_BINDIR=\""$(bindir)"\" \
- -I$(top_srcdir) \
- $(SHARED_CFLAGS)
-
-libwapiincludedir = $(includedir)/mono-$(API_VER)/mono/io-layer
-
-OTHER_H = \
- error.h \
- io.h \
- io-trace.h \
- io-layer.h \
- io-portability.h \
- uglify.h \
- wapi.h \
- wapi-remap.h
-
-OTHER_SRC = \
- error.c \
- error.h \
- io.c \
- io.h \
- io-portability.c \
- io-portability.h \
- io-private.h \
- io-layer.h \
- locking.c \
- posix.c \
- uglify.h \
- wapi_glob.h \
- wapi_glob.c \
- wapi.h \
- wapi-private.h \
- wapi.c
-
-
-WINDOWS_H = \
- io-layer.h
-
-WINDOWS_SRC = \
- io-layer.h \
- io-layer-dummy.c
-
-if HOST_WIN32
-libwapi_la_SOURCES = $(WINDOWS_SRC) $(WINDOWS_H)
-else
-libwapi_la_SOURCES = $(OTHER_SRC) $(OTHER_H)
-endif
-if PLATFORM_DARWIN
-libwapi_la_LIBADD = -lproc
-endif
-
-EXTRA_DIST = \
- $(WINDOWS_SRC)
- $(OTHER_SRC)
-
-
+++ /dev/null
-/*
- * error.c: Error reporting
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <pthread.h>
-#include <string.h>
-#include <errno.h>
-
-#include "mono/io-layer/wapi.h"
-#include "mono/io-layer/wapi-private.h"
-#include "mono/utils/mono-lazy-init.h"
-
-static pthread_key_t error_key;
-static mono_lazy_init_t error_key_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
-
-static void error_init(void)
-{
- int ret;
-
- ret = pthread_key_create(&error_key, NULL);
- g_assert (ret == 0);
-}
-
-static void error_cleanup (void)
-{
- int ret;
-
- ret = pthread_key_delete (error_key);
- g_assert (ret == 0);
-}
-
-void _wapi_error_cleanup (void)
-{
- mono_lazy_cleanup (&error_key_once, error_cleanup);
-}
-
-/**
- * GetLastError:
- *
- * Retrieves the last error that occurred in the calling thread.
- *
- * Return value: The error code for the last error that happened on
- * the calling thread.
- */
-guint32 GetLastError(void)
-{
- guint32 err;
- void *errptr;
-
- if (_wapi_has_shut_down)
- return 0;
- mono_lazy_initialize(&error_key_once, error_init);
- errptr=pthread_getspecific(error_key);
- err=GPOINTER_TO_UINT(errptr);
-
- return(err);
-}
-
-/**
- * SetLastError:
- * @code: The error code.
- *
- * Sets the error code in the calling thread.
- */
-void SetLastError(guint32 code)
-{
- int ret;
-
- if (_wapi_has_shut_down)
- return;
- /* Set the thread-local error code */
- mono_lazy_initialize(&error_key_once, error_init);
- ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
- g_assert (ret == 0);
-}
-
-gint
-_wapi_get_win32_file_error (gint err)
-{
- gint ret;
- /* mapping ideas borrowed from wine. they may need some work */
-
- switch (err) {
- case EACCES: case EPERM: case EROFS:
- ret = ERROR_ACCESS_DENIED;
- break;
-
- case EAGAIN:
- ret = ERROR_SHARING_VIOLATION;
- break;
-
- case EBUSY:
- ret = ERROR_LOCK_VIOLATION;
- break;
-
- case EEXIST:
- ret = ERROR_FILE_EXISTS;
- break;
-
- case EINVAL: case ESPIPE:
- ret = ERROR_SEEK;
- break;
-
- case EISDIR:
- ret = ERROR_CANNOT_MAKE;
- break;
-
- case ENFILE: case EMFILE:
- ret = ERROR_TOO_MANY_OPEN_FILES;
- break;
-
- case ENOENT: case ENOTDIR:
- ret = ERROR_FILE_NOT_FOUND;
- break;
-
- case ENOSPC:
- ret = ERROR_HANDLE_DISK_FULL;
- break;
-
- case ENOTEMPTY:
- ret = ERROR_DIR_NOT_EMPTY;
- break;
-
- case ENOEXEC:
- ret = ERROR_BAD_FORMAT;
- break;
-
- case ENAMETOOLONG:
- ret = ERROR_FILENAME_EXCED_RANGE;
- break;
-
-#ifdef EINPROGRESS
- case EINPROGRESS:
- ret = ERROR_IO_PENDING;
- break;
-#endif
-
- case ENOSYS:
- ret = ERROR_NOT_SUPPORTED;
- break;
-
- case EBADF:
- ret = ERROR_INVALID_HANDLE;
- break;
-
- case EIO:
- ret = ERROR_INVALID_HANDLE;
- break;
-
- case EINTR:
- ret = ERROR_IO_PENDING; /* best match I could find */
- break;
-
- case EPIPE:
- ret = ERROR_WRITE_FAULT;
- break;
-
- default:
- g_message ("Unknown errno: %s\n", g_strerror (err));
- ret = ERROR_GEN_FAILURE;
- break;
- }
-
- return ret;
-}
-
+++ /dev/null
-/*
- * error.h: Error reporting
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_ERROR_H_
-#define _WAPI_ERROR_H_
-
-typedef enum {
- ERROR_SUCCESS = 0,
- ERROR_FILE_NOT_FOUND = 2,
- ERROR_PATH_NOT_FOUND = 3,
- ERROR_TOO_MANY_OPEN_FILES = 4,
- ERROR_ACCESS_DENIED = 5,
- ERROR_INVALID_HANDLE = 6,
- ERROR_NOT_ENOUGH_MEMORY = 8,
- ERROR_BAD_FORMAT = 11,
- ERROR_INVALID_ACCESS = 12,
- ERROR_INVALID_DATA = 13,
- ERROR_OUTOFMEMORY = 14,
- ERROR_NOT_SAME_DEVICE = 17,
- ERROR_NO_MORE_FILES = 18,
- ERROR_BAD_LENGTH = 24,
- ERROR_SEEK = 25,
- ERROR_WRITE_FAULT = 29,
- ERROR_GEN_FAILURE = 31,
- ERROR_SHARING_VIOLATION = 32,
- ERROR_LOCK_VIOLATION = 33,
- ERROR_HANDLE_DISK_FULL = 39,
- ERROR_NOT_SUPPORTED = 50,
- ERROR_FILE_EXISTS = 80,
- ERROR_CANNOT_MAKE = 82,
- ERROR_INVALID_PARAMETER = 87,
- ERROR_INVALID_NAME = 123,
- ERROR_PROC_NOT_FOUND = 127,
- ERROR_DIR_NOT_EMPTY = 145,
- ERROR_ALREADY_EXISTS = 183,
- ERROR_BAD_EXE_FORMAT = 193,
- ERROR_FILENAME_EXCED_RANGE = 206,
- ERROR_DIRECTORY = 267,
- ERROR_IO_PENDING = 997,
- ERROR_ENCRYPTION_FAILED = 6000,
- WSAEINTR = 10004,
- WSAEBADF = 10009,
- WSAEACCES = 10013,
- WSAEFAULT = 10014,
- WSAEINVAL = 10022,
- WSAEMFILE = 10024,
- WSAEWOULDBLOCK = 10035,
- WSAEINPROGRESS = 10036,
- WSAEALREADY = 10037,
- WSAENOTSOCK = 10038,
- WSAEDESTADDRREQ = 10039,
- WSAEMSGSIZE = 10040,
- WSAENOPROTOOPT = 10042,
- WSAEPROTONOSUPPORT = 10043,
- WSAESOCKTNOSUPPORT = 10044,
- WSAEOPNOTSUPP = 10045,
- WSAEAFNOSUPPORT = 10047,
- WSAEADDRINUSE = 10048,
- WSAEADDRNOTAVAIL = 10049,
- WSAENETDOWN = 10050,
- WSAENETUNREACH = 10051,
- WSAECONNRESET = 10054,
- WSAENOBUFS = 10055,
- WSAEISCONN = 10056,
- WSAENOTCONN = 10057,
- WSAESHUTDOWN = 10058,
- WSAETIMEDOUT = 10060,
- WSAECONNREFUSED = 10061,
- WSAEHOSTDOWN = 10064,
- WSAEHOSTUNREACH = 10065,
- WSASYSCALLFAILURE = 10107,
-} WapiError;
-
-G_BEGIN_DECLS
-
-guint32 GetLastError (void);
-void SetLastError (guint32 code);
-gint _wapi_get_win32_file_error (gint err);
-void _wapi_error_cleanup (void);
-
-G_END_DECLS
-
-#endif /* _WAPI_ERROR_H_ */
+++ /dev/null
-/*
- * io-layer-dummy.c: Dummy file to fill the library on windows
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-extern char *_mono_iolayer_dummylib;
-char *_mono_iolayer_dummylib="This is a dummy library that isn't needed on Windows";
+++ /dev/null
-/*
- * io-layer.h: Include the right files depending on platform. This
- * file is the only entry point into the io-layer library.
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _MONO_IOLAYER_IOLAYER_H_
-#define _MONO_IOLAYER_IOLAYER_H_
-
-#include <config.h>
-#include <glib.h>
-
-#if defined(__WIN32__) || defined(_WIN32)
-/* Native win32 */
-#define __USE_W32_SOCKETS
-#include <winsock2.h>
-#include <windows.h>
-#include <winbase.h>
-/*
- * The mingw version says:
- * /usr/i686-pc-mingw32/sys-root/mingw/include/ws2tcpip.h:38:2: error: #error "ws2tcpip.h is not compatible with winsock.h. Include winsock2.h instead."
- */
-#ifdef _MSC_VER
-#include <ws2tcpip.h>
-#endif
-#include <psapi.h>
-
- /*
- * Workaround for missing WSAPOLLFD typedef in mingw's winsock2.h that is required for mswsock.h below.
- * Remove once http://sourceforge.net/p/mingw/bugs/1980/ is fixed.
- */
-#if defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION == 4
-typedef struct pollfd {
- SOCKET fd;
- short events;
- short revents;
-} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
-#endif
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-#include <mswsock.h>
-#endif
-
-#else /* EVERYONE ELSE */
-#include "mono/io-layer/wapi.h"
-#include "mono/io-layer/uglify.h"
-#endif /* HOST_WIN32 */
-
-#ifdef __native_client__
-#include "mono/metadata/nacl-stub.h"
-#endif
-
-#endif /* _MONO_IOLAYER_IOLAYER_H_ */
+++ /dev/null
-/*
- * io-portability.c: Optional filename mangling to try to cope with
- * badly-written non-portable windows apps
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * Copyright (c) 2006 Novell, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-#endif
-#include <utime.h>
-#include <sys/stat.h>
-
-#include <mono/io-layer/error.h>
-#include <mono/io-layer/wapi_glob.h>
-#include <mono/io-layer/io-portability.h>
-#include <mono/utils/mono-io-portability.h>
-
-#undef DEBUG
-
-int _wapi_open (const char *pathname, int flags, mode_t mode)
-{
- int fd;
- gchar *located_filename;
-
- if (flags & O_CREAT) {
- located_filename = mono_portability_find_file (pathname, FALSE);
- if (located_filename == NULL) {
- fd = open (pathname, flags, mode);
- } else {
- fd = open (located_filename, flags, mode);
- g_free (located_filename);
- }
- } else {
- fd = open (pathname, flags, mode);
- if (fd == -1 &&
- (errno == ENOENT || errno == ENOTDIR) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- located_filename = mono_portability_find_file (pathname, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return (-1);
- }
-
- fd = open (located_filename, flags, mode);
- g_free (located_filename);
- }
- }
-
-
- return(fd);
-}
-
-int _wapi_access (const char *pathname, int mode)
-{
- int ret;
-
- ret = access (pathname, mode);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (pathname, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = access (located_filename, mode);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_chmod (const char *pathname, mode_t mode)
-{
- int ret;
-
- ret = chmod (pathname, mode);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (pathname, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = chmod (located_filename, mode);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_utime (const char *filename, const struct utimbuf *buf)
-{
- int ret;
-
- ret = utime (filename, buf);
- if (ret == -1 &&
- errno == ENOENT &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (filename, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = utime (located_filename, buf);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_unlink (const char *pathname)
-{
- int ret;
-
- ret = unlink (pathname);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR || errno == EISDIR) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (pathname, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = unlink (located_filename);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_rename (const char *oldpath, const char *newpath)
-{
- int ret;
- gchar *located_newpath = mono_portability_find_file (newpath, FALSE);
-
- if (located_newpath == NULL) {
- ret = rename (oldpath, newpath);
- } else {
- ret = rename (oldpath, located_newpath);
-
- if (ret == -1 &&
- (errno == EISDIR || errno == ENAMETOOLONG ||
- errno == ENOENT || errno == ENOTDIR || errno == EXDEV) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_oldpath = mono_portability_find_file (oldpath, TRUE);
-
- if (located_oldpath == NULL) {
- g_free (located_oldpath);
- g_free (located_newpath);
-
- errno = saved_errno;
- return(-1);
- }
-
- ret = rename (located_oldpath, located_newpath);
- g_free (located_oldpath);
- }
- g_free (located_newpath);
- }
-
- return(ret);
-}
-
-int _wapi_stat (const char *path, struct stat *buf)
-{
- int ret;
-
- ret = stat (path, buf);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (path, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = stat (located_filename, buf);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_lstat (const char *path, struct stat *buf)
-{
- int ret;
-
- ret = lstat (path, buf);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (path, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = lstat (located_filename, buf);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_mkdir (const char *pathname, mode_t mode)
-{
- int ret;
- gchar *located_filename = mono_portability_find_file (pathname, FALSE);
-
- if (located_filename == NULL) {
- ret = mkdir (pathname, mode);
- } else {
- ret = mkdir (located_filename, mode);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_rmdir (const char *pathname)
-{
- int ret;
-
- ret = rmdir (pathname);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (pathname, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = rmdir (located_filename);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-int _wapi_chdir (const char *path)
-{
- int ret;
-
- ret = chdir (path);
- if (ret == -1 &&
- (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) &&
- IS_PORTABILITY_SET) {
- int saved_errno = errno;
- gchar *located_filename = mono_portability_find_file (path, TRUE);
-
- if (located_filename == NULL) {
- errno = saved_errno;
- return(-1);
- }
-
- ret = chdir (located_filename);
- g_free (located_filename);
- }
-
- return(ret);
-}
-
-gchar *_wapi_basename (const gchar *filename)
-{
- gchar *new_filename = g_strdup (filename), *ret;
-
- if (IS_PORTABILITY_SET) {
- g_strdelimit (new_filename, "\\", '/');
- }
-
- if (IS_PORTABILITY_DRIVE &&
- g_ascii_isalpha (new_filename[0]) &&
- (new_filename[1] == ':')) {
- int len = strlen (new_filename);
-
- g_memmove (new_filename, new_filename + 2, len - 2);
- new_filename[len - 2] = '\0';
- }
-
- ret = g_path_get_basename (new_filename);
- g_free (new_filename);
-
- return(ret);
-}
-
-gchar *_wapi_dirname (const gchar *filename)
-{
- gchar *new_filename = g_strdup (filename), *ret;
-
- if (IS_PORTABILITY_SET) {
- g_strdelimit (new_filename, "\\", '/');
- }
-
- if (IS_PORTABILITY_DRIVE &&
- g_ascii_isalpha (new_filename[0]) &&
- (new_filename[1] == ':')) {
- int len = strlen (new_filename);
-
- g_memmove (new_filename, new_filename + 2, len - 2);
- new_filename[len - 2] = '\0';
- }
-
- ret = g_path_get_dirname (new_filename);
- g_free (new_filename);
-
- return(ret);
-}
-
-GDir *_wapi_g_dir_open (const gchar *path, guint flags, GError **error)
-{
- GDir *ret;
-
- ret = g_dir_open (path, flags, error);
- if (ret == NULL &&
- ((*error)->code == G_FILE_ERROR_NOENT ||
- (*error)->code == G_FILE_ERROR_NOTDIR ||
- (*error)->code == G_FILE_ERROR_NAMETOOLONG) &&
- IS_PORTABILITY_SET) {
- gchar *located_filename = mono_portability_find_file (path, TRUE);
- GError *tmp_error = NULL;
-
- if (located_filename == NULL) {
- return(NULL);
- }
-
- ret = g_dir_open (located_filename, flags, &tmp_error);
- g_free (located_filename);
- if (tmp_error == NULL) {
- g_clear_error (error);
- }
- }
-
- return(ret);
-}
-
-
-static gint
-file_compare (gconstpointer a, gconstpointer b)
-{
- gchar *astr = *(gchar **) a;
- gchar *bstr = *(gchar **) b;
-
- return strcmp (astr, bstr);
-}
-
-static gint
-get_errno_from_g_file_error (gint error)
-{
- switch (error) {
-#ifdef EACCESS
- case G_FILE_ERROR_ACCES:
- error = EACCES;
- break;
-#endif
-#ifdef ENAMETOOLONG
- case G_FILE_ERROR_NAMETOOLONG:
- error = ENAMETOOLONG;
- break;
-#endif
-#ifdef ENOENT
- case G_FILE_ERROR_NOENT:
- error = ENOENT;
- break;
-#endif
-#ifdef ENOTDIR
- case G_FILE_ERROR_NOTDIR:
- error = ENOTDIR;
- break;
-#endif
-#ifdef ENXIO
- case G_FILE_ERROR_NXIO:
- error = ENXIO;
- break;
-#endif
-#ifdef ENODEV
- case G_FILE_ERROR_NODEV:
- error = ENODEV;
- break;
-#endif
-#ifdef EROFS
- case G_FILE_ERROR_ROFS:
- error = EROFS;
- break;
-#endif
-#ifdef ETXTBSY
- case G_FILE_ERROR_TXTBSY:
- error = ETXTBSY;
- break;
-#endif
-#ifdef EFAULT
- case G_FILE_ERROR_FAULT:
- error = EFAULT;
- break;
-#endif
-#ifdef ELOOP
- case G_FILE_ERROR_LOOP:
- error = ELOOP;
- break;
-#endif
-#ifdef ENOSPC
- case G_FILE_ERROR_NOSPC:
- error = ENOSPC;
- break;
-#endif
-#ifdef ENOMEM
- case G_FILE_ERROR_NOMEM:
- error = ENOMEM;
- break;
-#endif
-#ifdef EMFILE
- case G_FILE_ERROR_MFILE:
- error = EMFILE;
- break;
-#endif
-#ifdef ENFILE
- case G_FILE_ERROR_NFILE:
- error = ENFILE;
- break;
-#endif
-#ifdef EBADF
- case G_FILE_ERROR_BADF:
- error = EBADF;
- break;
-#endif
-#ifdef EINVAL
- case G_FILE_ERROR_INVAL:
- error = EINVAL;
- break;
-#endif
-#ifdef EPIPE
- case G_FILE_ERROR_PIPE:
- error = EPIPE;
- break;
-#endif
-#ifdef EAGAIN
- case G_FILE_ERROR_AGAIN:
- error = EAGAIN;
- break;
-#endif
-#ifdef EINTR
- case G_FILE_ERROR_INTR:
- error = EINTR;
- break;
-#endif
-#ifdef EWIO
- case G_FILE_ERROR_IO:
- error = EIO;
- break;
-#endif
-#ifdef EPERM
- case G_FILE_ERROR_PERM:
- error = EPERM;
- break;
-#endif
- case G_FILE_ERROR_FAILED:
- error = ERROR_INVALID_PARAMETER;
- break;
- }
-
- return error;
-}
-
-/* scandir using glib */
-gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
- gchar ***namelist)
-{
- GError *error = NULL;
- GDir *dir;
- GPtrArray *names;
- gint result;
- wapi_glob_t glob_buf;
- int flags = 0, i;
-
- dir = _wapi_g_dir_open (dirname, 0, &error);
- if (dir == NULL) {
- /* g_dir_open returns ENOENT on directories on which we don't
- * have read/x permission */
- gint errnum = get_errno_from_g_file_error (error->code);
- g_error_free (error);
- if (errnum == ENOENT &&
- !_wapi_access (dirname, F_OK) &&
- _wapi_access (dirname, R_OK|X_OK)) {
- errnum = EACCES;
- }
-
- errno = errnum;
- return -1;
- }
-
- if (IS_PORTABILITY_CASE) {
- flags = WAPI_GLOB_IGNORECASE;
- }
-
- result = _wapi_glob (dir, pattern, flags, &glob_buf);
- if (g_str_has_suffix (pattern, ".*")) {
- /* Special-case the patterns ending in '.*', as
- * windows also matches entries with no extension with
- * this pattern.
- *
- * TODO: should this be a MONO_IOMAP option?
- */
- gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2);
- gint result2;
-
- g_dir_rewind (dir);
- result2 = _wapi_glob (dir, pattern2, flags | WAPI_GLOB_APPEND | WAPI_GLOB_UNIQUE, &glob_buf);
-
- g_free (pattern2);
-
- if (result != 0) {
- result = result2;
- }
- }
-
- g_dir_close (dir);
- if (glob_buf.gl_pathc == 0) {
- return(0);
- } else if (result != 0) {
- return(-1);
- }
-
- names = g_ptr_array_new ();
- for (i = 0; i < glob_buf.gl_pathc; i++) {
- g_ptr_array_add (names, g_strdup (glob_buf.gl_pathv[i]));
- }
-
- _wapi_globfree (&glob_buf);
-
- result = names->len;
- if (result > 0) {
- g_ptr_array_sort (names, file_compare);
- g_ptr_array_set_size (names, result + 1);
-
- *namelist = (gchar **) g_ptr_array_free (names, FALSE);
- } else {
- g_ptr_array_free (names, TRUE);
- }
-
- return result;
-}
+++ /dev/null
-/*
- * io-portability.h: Optional filename mangling to try to cope with
- * badly-written non-portable windows apps
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * Copyright (C) 2006 Novell, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef _WAPI_IO_PORTABILITY_H_
-#define _WAPI_IO_PORTABILITY_H_
-
-#include <glib.h>
-#include <sys/types.h>
-#include <utime.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-G_BEGIN_DECLS
-
-extern int _wapi_open (const char *pathname, int flags, mode_t mode);
-extern int _wapi_access (const char *pathname, int mode);
-extern int _wapi_chmod (const char *pathname, mode_t mode);
-extern int _wapi_utime (const char *filename, const struct utimbuf *buf);
-extern int _wapi_unlink (const char *pathname);
-extern int _wapi_rename (const char *oldpath, const char *newpath);
-extern int _wapi_stat (const char *path, struct stat *buf);
-extern int _wapi_lstat (const char *path, struct stat *buf);
-extern int _wapi_mkdir (const char *pathname, mode_t mode);
-extern int _wapi_rmdir (const char *pathname);
-extern int _wapi_chdir (const char *path);
-extern gchar *_wapi_basename (const gchar *filename);
-extern gchar *_wapi_dirname (const gchar *filename);
-extern GDir *_wapi_g_dir_open (const gchar *path, guint flags, GError **error);
-extern gint _wapi_io_scandir (const gchar *dirname, const gchar *pattern,
- gchar ***namelist);
-
-G_END_DECLS
-
-#endif /* _WAPI_IO_PORTABILITY_H_ */
+++ /dev/null
-/*
- * io-private.h: Private definitions for file, console and find handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef _WAPI_IO_PRIVATE_H_
-#define _WAPI_IO_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-
-#include <mono/io-layer/io.h>
-#include <mono/io-layer/wapi-private.h>
-
-extern gboolean _wapi_lock_file_region (int fd, off_t offset, off_t length);
-extern gboolean _wapi_unlock_file_region (int fd, off_t offset, off_t length);
-extern gpointer _wapi_stdhandle_create (int fd, const gchar *name);
-
-/* Currently used for both FILE, CONSOLE and PIPE handle types. This may
- * have to change in future.
- */
-struct _WapiHandle_file
-{
- gchar *filename;
- struct _WapiFileShare *share_info; /* Pointer into shared mem */
- int fd;
- guint32 security_attributes;
- guint32 fileaccess;
- guint32 sharemode;
- guint32 attrs;
-};
-
-struct _WapiHandle_find
-{
- gchar **namelist;
- gchar *dir_part;
- int num;
- size_t count;
-};
-
-#endif /* _WAPI_IO_PRIVATE_H_ */
+++ /dev/null
-/*
- * io-trace.h: tracing macros
- *
- * Authors:
- * Marek Habersack <grendel@twistedcode.net>
- *
- * Copyright 2016 Xamarin, Inc (http://xamarin.com/)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef __IO_TRACE_H
-
-#ifdef DISABLE_IO_LAYER_TRACE
-#define MONO_TRACE(...)
-#else
-#include "mono/utils/mono-logger-internals.h"
-#define MONO_TRACE(...) mono_trace (__VA_ARGS__)
-#endif
-
-#endif
+++ /dev/null
-/*
- * io.c: File, console and find handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright (c) 2002-2006 Novell, Inc.
- * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#ifdef HAVE_SYS_STATVFS_H
-#include <sys/statvfs.h>
-#endif
-#if defined(HAVE_SYS_STATFS_H)
-#include <sys/statfs.h>
-#endif
-#if defined(HAVE_SYS_PARAM_H) && defined(HAVE_SYS_MOUNT_H)
-#include <sys/param.h>
-#include <sys/mount.h>
-#endif
-#include <sys/types.h>
-#include <stdio.h>
-#include <utime.h>
-#ifdef __linux__
-#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include <mono/utils/linux_magic.h>
-#endif
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/io-portability.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/strenc.h>
-#include <mono/utils/mono-once.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-/*
- * If SHM is disabled, this will point to a hash of _WapiFileShare structures, otherwise
- * it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a
- * 4MB array.
- */
-static GHashTable *file_share_hash;
-static mono_mutex_t file_share_mutex;
-
-static void
-time_t_to_filetime (time_t timeval, WapiFileTime *filetime)
-{
- guint64 ticks;
-
- ticks = ((guint64)timeval * 10000000) + 116444736000000000ULL;
- filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
- filetime->dwHighDateTime = ticks >> 32;
-}
-
-static void
-_wapi_handle_share_release (_WapiFileShare *share_info)
-{
- /* Prevent new entries racing with us */
- mono_os_mutex_lock (&file_share_mutex);
-
- g_assert (share_info->handle_refs > 0);
- share_info->handle_refs -= 1;
-
- if (share_info->handle_refs == 0)
- g_hash_table_remove (file_share_hash, share_info);
-
- mono_os_mutex_unlock (&file_share_mutex);
-}
-
-static gint
-wapi_share_info_equal (gconstpointer ka, gconstpointer kb)
-{
- const _WapiFileShare *s1 = (const _WapiFileShare *)ka;
- const _WapiFileShare *s2 = (const _WapiFileShare *)kb;
-
- return (s1->device == s2->device && s1->inode == s2->inode) ? 1 : 0;
-}
-
-static guint
-wapi_share_info_hash (gconstpointer data)
-{
- const _WapiFileShare *s = (const _WapiFileShare *)data;
-
- return s->inode;
-}
-
-static gboolean
-_wapi_handle_get_or_set_share (guint64 device, guint64 inode, guint32 new_sharemode, guint32 new_access,
- guint32 *old_sharemode, guint32 *old_access, struct _WapiFileShare **share_info)
-{
- struct _WapiFileShare *file_share;
- gboolean exists = FALSE;
-
- /* Prevent new entries racing with us */
- mono_os_mutex_lock (&file_share_mutex);
-
- _WapiFileShare tmp;
-
- /*
- * Instead of allocating a 4MB array, we use a hash table to keep track of this
- * info. This is needed even if SHM is disabled, to track sharing inside
- * the current process.
- */
- if (!file_share_hash)
- file_share_hash = g_hash_table_new_full (wapi_share_info_hash, wapi_share_info_equal, NULL, g_free);
-
- tmp.device = device;
- tmp.inode = inode;
-
- file_share = (_WapiFileShare *)g_hash_table_lookup (file_share_hash, &tmp);
- if (file_share) {
- *old_sharemode = file_share->sharemode;
- *old_access = file_share->access;
- *share_info = file_share;
-
- g_assert (file_share->handle_refs > 0);
- file_share->handle_refs += 1;
-
- exists = TRUE;
- } else {
- file_share = g_new0 (_WapiFileShare, 1);
-
- file_share->device = device;
- file_share->inode = inode;
- file_share->opened_by_pid = wapi_getpid ();
- file_share->sharemode = new_sharemode;
- file_share->access = new_access;
- file_share->handle_refs = 1;
- *share_info = file_share;
-
- g_hash_table_insert (file_share_hash, file_share, file_share);
- }
-
- mono_os_mutex_unlock (&file_share_mutex);
-
- return(exists);
-}
-
-static void file_close (gpointer handle, gpointer data);
-static void file_details (gpointer data);
-static const gchar* file_typename (void);
-static gsize file_typesize (void);
-static WapiFileType file_getfiletype(void);
-static gboolean file_read(gpointer handle, gpointer buffer,
- guint32 numbytes, guint32 *bytesread,
- WapiOverlapped *overlapped);
-static gboolean file_write(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped);
-static gboolean file_flush(gpointer handle);
-static guint32 file_seek(gpointer handle, gint32 movedistance,
- gint32 *highmovedistance, WapiSeekMethod method);
-static gboolean file_setendoffile(gpointer handle);
-static guint32 file_getfilesize(gpointer handle, guint32 *highsize);
-static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
- WapiFileTime *last_access,
- WapiFileTime *last_write);
-static gboolean file_setfiletime(gpointer handle,
- const WapiFileTime *create_time,
- const WapiFileTime *last_access,
- const WapiFileTime *last_write);
-static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
-
-/* File handle is only signalled for overlapped IO */
-static MonoW32HandleOps _wapi_file_ops = {
- file_close, /* close */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- file_details, /* details */
- file_typename, /* typename */
- file_typesize, /* typesize */
-};
-
-static void console_close (gpointer handle, gpointer data);
-static void console_details (gpointer data);
-static const gchar* console_typename (void);
-static gsize console_typesize (void);
-static WapiFileType console_getfiletype(void);
-static gboolean console_read(gpointer handle, gpointer buffer,
- guint32 numbytes, guint32 *bytesread,
- WapiOverlapped *overlapped);
-static gboolean console_write(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped);
-
-/* Console is mostly the same as file, except it can block waiting for
- * input or output
- */
-static MonoW32HandleOps _wapi_console_ops = {
- console_close, /* close */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- console_details, /* details */
- console_typename, /* typename */
- console_typesize, /* typesize */
-};
-
-static const gchar* find_typename (void);
-static gsize find_typesize (void);
-
-static MonoW32HandleOps _wapi_find_ops = {
- NULL, /* close */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- NULL, /* details */
- find_typename, /* typename */
- find_typesize, /* typesize */
-};
-
-static void pipe_close (gpointer handle, gpointer data);
-static void pipe_details (gpointer data);
-static const gchar* pipe_typename (void);
-static gsize pipe_typesize (void);
-static WapiFileType pipe_getfiletype (void);
-static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes,
- guint32 *bytesread, WapiOverlapped *overlapped);
-static gboolean pipe_write (gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped);
-
-/* Pipe handles
- */
-static MonoW32HandleOps _wapi_pipe_ops = {
- pipe_close, /* close */
- NULL, /* signal */
- NULL, /* own */
- NULL, /* is_owned */
- NULL, /* special_wait */
- NULL, /* prewait */
- pipe_details, /* details */
- pipe_typename, /* typename */
- pipe_typesize, /* typesize */
-};
-
-static const struct {
- /* File, console and pipe handles */
- WapiFileType (*getfiletype)(void);
-
- /* File, console and pipe handles */
- gboolean (*readfile)(gpointer handle, gpointer buffer,
- guint32 numbytes, guint32 *bytesread,
- WapiOverlapped *overlapped);
- gboolean (*writefile)(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped);
- gboolean (*flushfile)(gpointer handle);
-
- /* File handles */
- guint32 (*seek)(gpointer handle, gint32 movedistance,
- gint32 *highmovedistance, WapiSeekMethod method);
- gboolean (*setendoffile)(gpointer handle);
- guint32 (*getfilesize)(gpointer handle, guint32 *highsize);
- gboolean (*getfiletime)(gpointer handle, WapiFileTime *create_time,
- WapiFileTime *last_access,
- WapiFileTime *last_write);
- gboolean (*setfiletime)(gpointer handle,
- const WapiFileTime *create_time,
- const WapiFileTime *last_access,
- const WapiFileTime *last_write);
-} io_ops[MONO_W32HANDLE_COUNT]={
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* file */
- {file_getfiletype,
- file_read, file_write,
- file_flush, file_seek,
- file_setendoffile,
- file_getfilesize,
- file_getfiletime,
- file_setfiletime},
- /* console */
- {console_getfiletype,
- console_read,
- console_write,
- NULL, NULL, NULL, NULL, NULL, NULL},
- /* thread */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* sem */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* mutex */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* event */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* socket (will need at least read and write) */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* find */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* process */
- {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
- /* pipe */
- {pipe_getfiletype,
- pipe_read,
- pipe_write,
- NULL, NULL, NULL, NULL, NULL, NULL},
-};
-
-static gboolean lock_while_writing = FALSE;
-
-/* Some utility functions.
- */
-
-/*
- * Check if a file is writable by the current user.
- *
- * This is is a best effort kind of thing. It assumes a reasonable sane set
- * of permissions by the underlying OS.
- *
- * We generally assume that basic unix permission bits are authoritative. Which might not
- * be the case under systems with extended permissions systems (posix ACLs, SELinux, OSX/iOS sandboxing, etc)
- *
- * The choice of access as the fallback is due to the expected lower overhead compared to trying to open the file.
- *
- * The only expected problem with using access are for root, setuid or setgid programs as access is not consistent
- * under those situations. It's to be expected that this should not happen in practice as those bits are very dangerous
- * and should not be used with a dynamic runtime.
- */
-static gboolean
-is_file_writable (struct stat *st, const char *path)
-{
-#if __APPLE__
- // OS X Finder "locked" or `ls -lO` "uchg".
- // This only covers one of several cases where an OS X file could be unwritable through special flags.
- if (st->st_flags & (UF_IMMUTABLE|SF_IMMUTABLE))
- return 0;
-#endif
-
- /* Is it globally writable? */
- if (st->st_mode & S_IWOTH)
- return 1;
-
- /* Am I the owner? */
- if ((st->st_uid == geteuid ()) && (st->st_mode & S_IWUSR))
- return 1;
-
- /* Am I in the same group? */
- if ((st->st_gid == getegid ()) && (st->st_mode & S_IWGRP))
- return 1;
-
- /* Fallback to using access(2). It's not ideal as it might not take into consideration euid/egid
- * but it's the only sane option we have on unix.
- */
- return access (path, W_OK) == 0;
-}
-
-
-static guint32 _wapi_stat_to_file_attributes (const gchar *pathname,
- struct stat *buf,
- struct stat *lbuf)
-{
- guint32 attrs = 0;
- gchar *filename;
-
- /* FIXME: this could definitely be better, but there seems to
- * be no pattern to the attributes that are set
- */
-
- /* Sockets (0140000) != Directory (040000) + Regular file (0100000) */
- if (S_ISSOCK (buf->st_mode))
- buf->st_mode &= ~S_IFSOCK; /* don't consider socket protection */
-
- filename = _wapi_basename (pathname);
-
- if (S_ISDIR (buf->st_mode)) {
- attrs = FILE_ATTRIBUTE_DIRECTORY;
- if (!is_file_writable (buf, pathname)) {
- attrs |= FILE_ATTRIBUTE_READONLY;
- }
- if (filename[0] == '.') {
- attrs |= FILE_ATTRIBUTE_HIDDEN;
- }
- } else {
- if (!is_file_writable (buf, pathname)) {
- attrs = FILE_ATTRIBUTE_READONLY;
-
- if (filename[0] == '.') {
- attrs |= FILE_ATTRIBUTE_HIDDEN;
- }
- } else if (filename[0] == '.') {
- attrs = FILE_ATTRIBUTE_HIDDEN;
- } else {
- attrs = FILE_ATTRIBUTE_NORMAL;
- }
- }
-
- if (lbuf != NULL) {
- if (S_ISLNK (lbuf->st_mode)) {
- attrs |= FILE_ATTRIBUTE_REPARSE_POINT;
- }
- }
-
- g_free (filename);
-
- return attrs;
-}
-
-static void
-_wapi_set_last_error_from_errno (void)
-{
- SetLastError (_wapi_get_win32_file_error (errno));
-}
-
-static void _wapi_set_last_path_error_from_errno (const gchar *dir,
- const gchar *path)
-{
- if (errno == ENOENT) {
- /* Check the path - if it's a missing directory then
- * we need to set PATH_NOT_FOUND not FILE_NOT_FOUND
- */
- gchar *dirname;
-
-
- if (dir == NULL) {
- dirname = _wapi_dirname (path);
- } else {
- dirname = g_strdup (dir);
- }
-
- if (_wapi_access (dirname, F_OK) == 0) {
- SetLastError (ERROR_FILE_NOT_FOUND);
- } else {
- SetLastError (ERROR_PATH_NOT_FOUND);
- }
-
- g_free (dirname);
- } else {
- _wapi_set_last_error_from_errno ();
- }
-}
-
-/* Handle ops.
- */
-static void file_close (gpointer handle, gpointer data)
-{
- struct _WapiHandle_file *file_handle = (struct _WapiHandle_file *)data;
- int fd = file_handle->fd;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing file handle %p [%s]", __func__, handle,
- file_handle->filename);
-
- if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE)
- _wapi_unlink (file_handle->filename);
-
- g_free (file_handle->filename);
-
- if (file_handle->share_info)
- _wapi_handle_share_release (file_handle->share_info);
-
- close (fd);
-}
-
-static void file_details (gpointer data)
-{
- struct _WapiHandle_file *file = (struct _WapiHandle_file *)data;
-
- g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u",
- file->filename,
- file->fileaccess&GENERIC_READ?'R':'.',
- file->fileaccess&GENERIC_WRITE?'W':'.',
- file->fileaccess&GENERIC_EXECUTE?'X':'.',
- file->sharemode&FILE_SHARE_READ?'R':'.',
- file->sharemode&FILE_SHARE_WRITE?'W':'.',
- file->sharemode&FILE_SHARE_DELETE?'D':'.',
- file->attrs);
-}
-
-static const gchar* file_typename (void)
-{
- return "File";
-}
-
-static gsize file_typesize (void)
-{
- return sizeof (struct _WapiHandle_file);
-}
-
-static WapiFileType file_getfiletype(void)
-{
- return(FILE_TYPE_DISK);
-}
-
-static gboolean file_read(gpointer handle, gpointer buffer,
- guint32 numbytes, guint32 *bytesread,
- WapiOverlapped *overlapped)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- int fd, ret;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- fd = file_handle->fd;
- if(bytesread!=NULL) {
- *bytesread=0;
- }
-
- if(!(file_handle->fileaccess & GENERIC_READ) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
- __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- do {
- ret = read (fd, buffer, numbytes);
- } while (ret == -1 && errno == EINTR &&
- !mono_thread_info_is_interrupt_state (info));
-
- if(ret==-1) {
- gint err = errno;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
- handle, strerror(err));
- SetLastError (_wapi_get_win32_file_error (err));
- return(FALSE);
- }
-
- if (bytesread != NULL) {
- *bytesread = ret;
- }
-
- return(TRUE);
-}
-
-static gboolean file_write(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- int ret, fd;
- off_t current_pos = 0;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- fd = file_handle->fd;
-
- if(byteswritten!=NULL) {
- *byteswritten=0;
- }
-
- if(!(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- if (lock_while_writing) {
- /* Need to lock the region we're about to write to,
- * because we only do advisory locking on POSIX
- * systems
- */
- current_pos = lseek (fd, (off_t)0, SEEK_CUR);
- if (current_pos == -1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
- handle, strerror (errno));
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- if (_wapi_lock_file_region (fd, current_pos,
- numbytes) == FALSE) {
- /* The error has already been set */
- return(FALSE);
- }
- }
-
- do {
- ret = write (fd, buffer, numbytes);
- } while (ret == -1 && errno == EINTR &&
- !mono_thread_info_is_interrupt_state (info));
-
- if (lock_while_writing) {
- _wapi_unlock_file_region (fd, current_pos, numbytes);
- }
-
- if (ret == -1) {
- if (errno == EINTR) {
- ret = 0;
- } else {
- _wapi_set_last_error_from_errno ();
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
- __func__, handle, strerror(errno));
-
- return(FALSE);
- }
- }
- if (byteswritten != NULL) {
- *byteswritten = ret;
- }
- return(TRUE);
-}
-
-static gboolean file_flush(gpointer handle)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- int ret, fd;
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- fd = file_handle->fd;
-
- if(!(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- ret=fsync(fd);
- if (ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
- strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-static guint32 file_seek(gpointer handle, gint32 movedistance,
- gint32 *highmovedistance, WapiSeekMethod method)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- gint64 offset, newpos;
- int whence, fd;
- guint32 ret;
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(INVALID_SET_FILE_POINTER);
- }
-
- fd = file_handle->fd;
-
- if(!(file_handle->fileaccess & GENERIC_READ) &&
- !(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(INVALID_SET_FILE_POINTER);
- }
-
- switch(method) {
- case FILE_BEGIN:
- whence=SEEK_SET;
- break;
- case FILE_CURRENT:
- whence=SEEK_CUR;
- break;
- case FILE_END:
- whence=SEEK_END;
- break;
- default:
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: invalid seek type %d", __func__, method);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(INVALID_SET_FILE_POINTER);
- }
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
- if(highmovedistance==NULL) {
- offset=movedistance;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld (low %d)", __func__,
- offset, movedistance);
- } else {
- offset=((gint64) *highmovedistance << 32) | (guint32)movedistance;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
- }
-#else
- offset=movedistance;
-#endif
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %lld bytes from %d", __func__,
- handle, (long long)offset, whence);
-
-#ifdef PLATFORM_ANDROID
- /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
- newpos=lseek64(fd, offset, whence);
-#else
- newpos=lseek(fd, offset, whence);
-#endif
- if(newpos==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
- __func__, handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(INVALID_SET_FILE_POINTER);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %lld", __func__, newpos);
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
- ret=newpos & 0xFFFFFFFF;
- if(highmovedistance!=NULL) {
- *highmovedistance=newpos>>32;
- }
-#else
- ret=newpos;
- if(highmovedistance!=NULL) {
- /* Accurate, but potentially dodgy :-) */
- *highmovedistance=0;
- }
-#endif
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %d/%d", __func__,
- handle, ret, highmovedistance==NULL?0:*highmovedistance);
-
- return(ret);
-}
-
-static gboolean file_setendoffile(gpointer handle)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- struct stat statbuf;
- off_t pos;
- int ret, fd;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = file_handle->fd;
-
- if(!(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- /* Find the current file position, and the file length. If
- * the file position is greater than the length, write to
- * extend the file with a hole. If the file position is less
- * than the length, truncate the file.
- */
-
- ret=fstat(fd, &statbuf);
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
- handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- pos=lseek(fd, (off_t)0, SEEK_CUR);
- if(pos==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
- handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
-#ifdef FTRUNCATE_DOESNT_EXTEND
- off_t size = statbuf.st_size;
- /* I haven't bothered to write the configure.ac stuff for this
- * because I don't know if any platform needs it. I'm leaving
- * this code just in case though
- */
- if(pos>size) {
- /* Extend the file. Use write() here, because some
- * manuals say that ftruncate() behaviour is undefined
- * when the file needs extending. The POSIX spec says
- * that on XSI-conformant systems it extends, so if
- * every system we care about conforms, then we can
- * drop this write.
- */
- do {
- ret = write (fd, "", 1);
- } while (ret == -1 && errno == EINTR &&
- !mono_thread_info_is_interrupt_state (info));
-
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- /* And put the file position back after the write */
- ret = lseek (fd, pos, SEEK_SET);
- if (ret == -1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
- __func__, handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
- }
-#endif
-
-/* Native Client has no ftruncate function, even in standalone sel_ldr. */
-#ifndef __native_client__
- /* always truncate, because the extend write() adds an extra
- * byte to the end of the file
- */
- do {
- ret=ftruncate(fd, pos);
- }
- while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ftruncate failed: %s", __func__,
- handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-#endif
-
- return(TRUE);
-}
-
-static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- struct stat statbuf;
- guint32 size;
- int ret;
- int fd;
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(INVALID_FILE_SIZE);
- }
- fd = file_handle->fd;
-
- if(!(file_handle->fileaccess & GENERIC_READ) &&
- !(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(INVALID_FILE_SIZE);
- }
-
- /* If the file has a size with the low bits 0xFFFFFFFF the
- * caller can't tell if this is an error, so clear the error
- * value
- */
- SetLastError (ERROR_SUCCESS);
-
- ret = fstat(fd, &statbuf);
- if (ret == -1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
- handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(INVALID_FILE_SIZE);
- }
-
- /* fstat indicates block devices as zero-length, so go a different path */
-#ifdef BLKGETSIZE64
- if (S_ISBLK(statbuf.st_mode)) {
- guint64 bigsize;
- if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
- __func__, handle, strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(INVALID_FILE_SIZE);
- }
-
- size = bigsize & 0xFFFFFFFF;
- if (highsize != NULL) {
- *highsize = bigsize>>32;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d",
- __func__, size, *highsize);
-
- return(size);
- }
-#endif
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
- size = statbuf.st_size & 0xFFFFFFFF;
- if (highsize != NULL) {
- *highsize = statbuf.st_size>>32;
- }
-#else
- if (highsize != NULL) {
- /* Accurate, but potentially dodgy :-) */
- *highsize = 0;
- }
- size = statbuf.st_size;
-#endif
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize);
-
- return(size);
-}
-
-static gboolean file_getfiletime(gpointer handle, WapiFileTime *create_time,
- WapiFileTime *last_access,
- WapiFileTime *last_write)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- struct stat statbuf;
- guint64 create_ticks, access_ticks, write_ticks;
- int ret, fd;
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = file_handle->fd;
-
- if(!(file_handle->fileaccess & GENERIC_READ) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
- __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- ret=fstat(fd, &statbuf);
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
- strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: atime: %ld ctime: %ld mtime: %ld", __func__,
- statbuf.st_atime, statbuf.st_ctime,
- statbuf.st_mtime);
-
- /* Try and guess a meaningful create time by using the older
- * of atime or ctime
- */
- /* The magic constant comes from msdn documentation
- * "Converting a time_t Value to a File Time"
- */
- if(statbuf.st_atime < statbuf.st_ctime) {
- create_ticks=((guint64)statbuf.st_atime*10000000)
- + 116444736000000000ULL;
- } else {
- create_ticks=((guint64)statbuf.st_ctime*10000000)
- + 116444736000000000ULL;
- }
-
- access_ticks=((guint64)statbuf.st_atime*10000000)+116444736000000000ULL;
- write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
- access_ticks, create_ticks, write_ticks);
-
- if(create_time!=NULL) {
- create_time->dwLowDateTime = create_ticks & 0xFFFFFFFF;
- create_time->dwHighDateTime = create_ticks >> 32;
- }
-
- if(last_access!=NULL) {
- last_access->dwLowDateTime = access_ticks & 0xFFFFFFFF;
- last_access->dwHighDateTime = access_ticks >> 32;
- }
-
- if(last_write!=NULL) {
- last_write->dwLowDateTime = write_ticks & 0xFFFFFFFF;
- last_write->dwHighDateTime = write_ticks >> 32;
- }
-
- return(TRUE);
-}
-
-static gboolean file_setfiletime(gpointer handle,
- const WapiFileTime *create_time G_GNUC_UNUSED,
- const WapiFileTime *last_access,
- const WapiFileTime *last_write)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- struct utimbuf utbuf;
- struct stat statbuf;
- guint64 access_ticks, write_ticks;
- int ret, fd;
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = file_handle->fd;
-
- if(!(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- if(file_handle->filename == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
-
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- /* Get the current times, so we can put the same times back in
- * the event that one of the FileTime structs is NULL
- */
- ret=fstat (fd, &statbuf);
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
- strerror(errno));
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- if(last_access!=NULL) {
- access_ticks=((guint64)last_access->dwHighDateTime << 32) +
- last_access->dwLowDateTime;
- /* This is (time_t)0. We can actually go to INT_MIN,
- * but this will do for now.
- */
- if (access_ticks < 116444736000000000ULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set access time too early",
- __func__);
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- if (sizeof (utbuf.actime) == 4 && ((access_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
- __func__);
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- utbuf.actime=(access_ticks - 116444736000000000ULL) / 10000000;
- } else {
- utbuf.actime=statbuf.st_atime;
- }
-
- if(last_write!=NULL) {
- write_ticks=((guint64)last_write->dwHighDateTime << 32) +
- last_write->dwLowDateTime;
- /* This is (time_t)0. We can actually go to INT_MIN,
- * but this will do for now.
- */
- if (write_ticks < 116444736000000000ULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time too early",
- __func__);
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
- if (sizeof (utbuf.modtime) == 4 && ((write_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
- __func__);
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- utbuf.modtime=(write_ticks - 116444736000000000ULL) / 10000000;
- } else {
- utbuf.modtime=statbuf.st_mtime;
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__,
- handle, utbuf.actime, utbuf.modtime);
-
- ret = _wapi_utime (file_handle->filename, &utbuf);
- if (ret == -1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p [%s] utime failed: %s", __func__,
- handle, file_handle->filename, strerror(errno));
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-static void console_close (gpointer handle, gpointer data)
-{
- struct _WapiHandle_file *console_handle = (struct _WapiHandle_file *)data;
- int fd = console_handle->fd;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing console handle %p", __func__, handle);
-
- g_free (console_handle->filename);
-
- if (fd > 2) {
- if (console_handle->share_info)
- _wapi_handle_share_release (console_handle->share_info);
- close (fd);
- }
-}
-
-static void console_details (gpointer data)
-{
- file_details (data);
-}
-
-static const gchar* console_typename (void)
-{
- return "Console";
-}
-
-static gsize console_typesize (void)
-{
- return sizeof (struct _WapiHandle_file);
-}
-
-static WapiFileType console_getfiletype(void)
-{
- return(FILE_TYPE_CHAR);
-}
-
-static gboolean console_read(gpointer handle, gpointer buffer,
- guint32 numbytes, guint32 *bytesread,
- WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
- struct _WapiHandle_file *console_handle;
- gboolean ok;
- int ret, fd;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
- (gpointer *)&console_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up console handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = console_handle->fd;
-
- if(bytesread!=NULL) {
- *bytesread=0;
- }
-
- if(!(console_handle->fileaccess & GENERIC_READ) &&
- !(console_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
- __func__, handle, console_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- do {
- ret=read(fd, buffer, numbytes);
- } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
-
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, handle,
- strerror(errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- if(bytesread!=NULL) {
- *bytesread=ret;
- }
-
- return(TRUE);
-}
-
-static gboolean console_write(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
- struct _WapiHandle_file *console_handle;
- gboolean ok;
- int ret, fd;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
- (gpointer *)&console_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up console handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = console_handle->fd;
-
- if(byteswritten!=NULL) {
- *byteswritten=0;
- }
-
- if(!(console_handle->fileaccess & GENERIC_WRITE) &&
- !(console_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- do {
- ret = write(fd, buffer, numbytes);
- } while (ret == -1 && errno == EINTR &&
- !mono_thread_info_is_interrupt_state (info));
-
- if (ret == -1) {
- if (errno == EINTR) {
- ret = 0;
- } else {
- _wapi_set_last_error_from_errno ();
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
- __func__, handle, strerror(errno));
-
- return(FALSE);
- }
- }
- if(byteswritten!=NULL) {
- *byteswritten=ret;
- }
-
- return(TRUE);
-}
-
-static const gchar* find_typename (void)
-{
- return "Find";
-}
-
-static gsize find_typesize (void)
-{
- return sizeof (struct _WapiHandle_find);
-}
-
-static void pipe_close (gpointer handle, gpointer data)
-{
- struct _WapiHandle_file *pipe_handle = (struct _WapiHandle_file*)data;
- int fd = pipe_handle->fd;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p fd %d", __func__, handle, fd);
-
- /* No filename with pipe handles */
-
- if (pipe_handle->share_info)
- _wapi_handle_share_release (pipe_handle->share_info);
-
- close (fd);
-}
-
-static void pipe_details (gpointer data)
-{
- file_details (data);
-}
-
-static const gchar* pipe_typename (void)
-{
- return "Pipe";
-}
-
-static gsize pipe_typesize (void)
-{
- return sizeof (struct _WapiHandle_file);
-}
-
-static WapiFileType pipe_getfiletype(void)
-{
- return(FILE_TYPE_PIPE);
-}
-
-static gboolean pipe_read (gpointer handle, gpointer buffer,
- guint32 numbytes, guint32 *bytesread,
- WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
- struct _WapiHandle_file *pipe_handle;
- gboolean ok;
- int ret, fd;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
- (gpointer *)&pipe_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up pipe handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = pipe_handle->fd;
-
- if(bytesread!=NULL) {
- *bytesread=0;
- }
-
- if(!(pipe_handle->fileaccess & GENERIC_READ) &&
- !(pipe_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
- __func__, handle, pipe_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %d bytes from pipe %p", __func__,
- numbytes, handle);
-
- do {
- ret=read(fd, buffer, numbytes);
- } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
-
- if (ret == -1) {
- if (errno == EINTR) {
- ret = 0;
- } else {
- _wapi_set_last_error_from_errno ();
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
- handle, strerror(errno));
-
- return(FALSE);
- }
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle);
-
- if(bytesread!=NULL) {
- *bytesread=ret;
- }
-
- return(TRUE);
-}
-
-static gboolean pipe_write(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped G_GNUC_UNUSED)
-{
- struct _WapiHandle_file *pipe_handle;
- gboolean ok;
- int ret, fd;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
- (gpointer *)&pipe_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up pipe handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
- fd = pipe_handle->fd;
-
- if(byteswritten!=NULL) {
- *byteswritten=0;
- }
-
- if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
- !(pipe_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
-
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %d bytes to pipe %p", __func__, numbytes,
- handle);
-
- do {
- ret = write (fd, buffer, numbytes);
- } while (ret == -1 && errno == EINTR &&
- !mono_thread_info_is_interrupt_state (info));
-
- if (ret == -1) {
- if (errno == EINTR) {
- ret = 0;
- } else {
- _wapi_set_last_error_from_errno ();
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
- handle, strerror(errno));
-
- return(FALSE);
- }
- }
- if(byteswritten!=NULL) {
- *byteswritten=ret;
- }
-
- return(TRUE);
-}
-
-static int convert_flags(guint32 fileaccess, guint32 createmode)
-{
- int flags=0;
-
- switch(fileaccess) {
- case GENERIC_READ:
- flags=O_RDONLY;
- break;
- case GENERIC_WRITE:
- flags=O_WRONLY;
- break;
- case GENERIC_READ|GENERIC_WRITE:
- flags=O_RDWR;
- break;
- default:
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__,
- fileaccess);
- break;
- }
-
- switch(createmode) {
- case CREATE_NEW:
- flags|=O_CREAT|O_EXCL;
- break;
- case CREATE_ALWAYS:
- flags|=O_CREAT|O_TRUNC;
- break;
- case OPEN_EXISTING:
- break;
- case OPEN_ALWAYS:
- flags|=O_CREAT;
- break;
- case TRUNCATE_EXISTING:
- flags|=O_TRUNC;
- break;
- default:
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__,
- createmode);
- break;
- }
-
- return(flags);
-}
-
-#if 0 /* unused */
-static mode_t convert_perms(guint32 sharemode)
-{
- mode_t perms=0600;
-
- if(sharemode&FILE_SHARE_READ) {
- perms|=044;
- }
- if(sharemode&FILE_SHARE_WRITE) {
- perms|=022;
- }
-
- return(perms);
-}
-#endif
-
-static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
- guint32 fileaccess,
- struct _WapiFileShare **share_info)
-{
- gboolean file_already_shared;
- guint32 file_existing_share, file_existing_access;
-
- file_already_shared = _wapi_handle_get_or_set_share (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info);
-
- if (file_already_shared) {
- /* The reference to this share info was incremented
- * when we looked it up, so be careful to put it back
- * if we conclude we can't use this file.
- */
- if (file_existing_share == 0) {
- /* Quick and easy, no possibility to share */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
-
- _wapi_handle_share_release (*share_info);
-
- return(FALSE);
- }
-
- if (((file_existing_share == FILE_SHARE_READ) &&
- (fileaccess != GENERIC_READ)) ||
- ((file_existing_share == FILE_SHARE_WRITE) &&
- (fileaccess != GENERIC_WRITE))) {
- /* New access mode doesn't match up */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
-
- _wapi_handle_share_release (*share_info);
-
- return(FALSE);
- }
-
- if (((file_existing_access & GENERIC_READ) &&
- !(sharemode & FILE_SHARE_READ)) ||
- ((file_existing_access & GENERIC_WRITE) &&
- !(sharemode & FILE_SHARE_WRITE))) {
- /* New share mode doesn't match up */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
-
- _wapi_handle_share_release (*share_info);
-
- return(FALSE);
- }
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
- }
-
- return(TRUE);
-}
-
-
-static gboolean
-share_allows_delete (struct stat *statbuf, struct _WapiFileShare **share_info)
-{
- gboolean file_already_shared;
- guint32 file_existing_share, file_existing_access;
-
- file_already_shared = _wapi_handle_get_or_set_share (statbuf->st_dev, statbuf->st_ino, FILE_SHARE_DELETE, GENERIC_READ, &file_existing_share, &file_existing_access, share_info);
-
- if (file_already_shared) {
- /* The reference to this share info was incremented
- * when we looked it up, so be careful to put it back
- * if we conclude we can't use this file.
- */
- if (file_existing_share == 0) {
- /* Quick and easy, no possibility to share */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, (*share_info)->access);
-
- _wapi_handle_share_release (*share_info);
-
- return(FALSE);
- }
-
- if (!(file_existing_share & FILE_SHARE_DELETE)) {
- /* New access mode doesn't match up */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, (*share_info)->access, file_existing_share);
-
- _wapi_handle_share_release (*share_info);
-
- return(FALSE);
- }
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
- }
-
- return(TRUE);
-}
-
-/**
- * CreateFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file or other object to create.
- * @fileaccess: specifies the file access mode
- * @sharemode: whether the file should be shared. This parameter is
- * currently ignored.
- * @security: Ignored for now.
- * @createmode: specifies whether to create a new file, whether to
- * overwrite an existing file, whether to truncate the file, etc.
- * @attrs: specifies file attributes and flags. On win32 attributes
- * are characteristics of the file, not the handle, and are ignored
- * when an existing file is opened. Flags give the library hints on
- * how to process a file to optimise performance.
- * @template: the handle of an open %GENERIC_READ file that specifies
- * attributes to apply to a newly created file, ignoring @attrs.
- * Normally this parameter is NULL. This parameter is ignored when an
- * existing file is opened.
- *
- * Creates a new file handle. This only applies to normal files:
- * pipes are handled by CreatePipe(), and console handles are created
- * with GetStdHandle().
- *
- * Return value: the new handle, or %INVALID_HANDLE_VALUE on error.
- */
-gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
- guint32 sharemode, WapiSecurityAttributes *security,
- guint32 createmode, guint32 attrs,
- gpointer template_ G_GNUC_UNUSED)
-{
- struct _WapiHandle_file file_handle = {0};
- gpointer handle;
- int flags=convert_flags(fileaccess, createmode);
- /*mode_t perms=convert_perms(sharemode);*/
- /* we don't use sharemode, because that relates to sharing of
- * the file when the file is open and is already handled by
- * other code, perms instead are the on-disk permissions and
- * this is a sane default.
- */
- mode_t perms=0666;
- gchar *filename;
- int fd, ret;
- MonoW32HandleType handle_type;
- struct stat statbuf;
-
- if (attrs & FILE_ATTRIBUTE_TEMPORARY)
- perms = 0600;
-
- if (attrs & FILE_ATTRIBUTE_ENCRYPTED){
- SetLastError (ERROR_ENCRYPTION_FAILED);
- return INVALID_HANDLE_VALUE;
- }
-
- if (name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(INVALID_HANDLE_VALUE);
- }
-
- filename = mono_unicode_to_external (name);
- if (filename == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(INVALID_HANDLE_VALUE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%x and access 0x%x", __func__,
- filename, sharemode, fileaccess);
-
- fd = _wapi_open (filename, flags, perms);
-
- /* If we were trying to open a directory with write permissions
- * (e.g. O_WRONLY or O_RDWR), this call will fail with
- * EISDIR. However, this is a bit bogus because calls to
- * manipulate the directory (e.g. SetFileTime) will still work on
- * the directory because they use other API calls
- * (e.g. utime()). Hence, if we failed with the EISDIR error, try
- * to open the directory again without write permission.
- */
- if (fd == -1 && errno == EISDIR)
- {
- /* Try again but don't try to make it writable */
- fd = _wapi_open (filename, flags & ~(O_RDWR|O_WRONLY), perms);
- }
-
- if (fd == -1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename,
- strerror(errno));
- _wapi_set_last_path_error_from_errno (NULL, filename);
- g_free (filename);
-
- return(INVALID_HANDLE_VALUE);
- }
-
- if (fd >= mono_w32handle_fd_reserve) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
-
- SetLastError (ERROR_TOO_MANY_OPEN_FILES);
-
- close (fd);
- g_free (filename);
-
- return(INVALID_HANDLE_VALUE);
- }
-
- ret = fstat (fd, &statbuf);
- if (ret == -1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__,
- filename, strerror (errno));
- _wapi_set_last_error_from_errno ();
- g_free (filename);
- close (fd);
-
- return(INVALID_HANDLE_VALUE);
- }
-#ifdef __native_client__
- /* Workaround: Native Client currently returns the same fake inode
- * for all files, so do a simple hash on the filename so we don't
- * use the same share info for each file.
- */
- statbuf.st_ino = g_str_hash(filename);
-#endif
-
- if (share_allows_open (&statbuf, sharemode, fileaccess,
- &file_handle.share_info) == FALSE) {
- SetLastError (ERROR_SHARING_VIOLATION);
- g_free (filename);
- close (fd);
-
- return (INVALID_HANDLE_VALUE);
- }
- if (file_handle.share_info == NULL) {
- /* No space, so no more files can be opened */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__);
-
- SetLastError (ERROR_TOO_MANY_OPEN_FILES);
- close (fd);
- g_free (filename);
-
- return(INVALID_HANDLE_VALUE);
- }
-
- file_handle.filename = filename;
-
- if(security!=NULL) {
- //file_handle->security_attributes=_wapi_handle_scratch_store (
- //security, sizeof(WapiSecurityAttributes));
- }
-
- file_handle.fd = fd;
- file_handle.fileaccess=fileaccess;
- file_handle.sharemode=sharemode;
- file_handle.attrs=attrs;
-
-#ifdef HAVE_POSIX_FADVISE
- if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
- posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
- if (attrs & FILE_FLAG_RANDOM_ACCESS)
- posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
-#endif
-
-#ifdef F_RDAHEAD
- if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
- fcntl(fd, F_RDAHEAD, 1);
-#endif
-
-#ifndef S_ISFIFO
-#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
-#endif
- if (S_ISFIFO (statbuf.st_mode)) {
- handle_type = MONO_W32HANDLE_PIPE;
- /* maintain invariant that pipes have no filename */
- file_handle.filename = NULL;
- g_free (filename);
- filename = NULL;
- } else if (S_ISCHR (statbuf.st_mode)) {
- handle_type = MONO_W32HANDLE_CONSOLE;
- } else {
- handle_type = MONO_W32HANDLE_FILE;
- }
-
- handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
- if (handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating file handle", __func__);
- g_free (filename);
- close (fd);
-
- SetLastError (ERROR_GEN_FAILURE);
- return(INVALID_HANDLE_VALUE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
-
- return(handle);
-}
-
-/**
- * DeleteFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file to be deleted.
- *
- * Deletes file @name.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean DeleteFile(const gunichar2 *name)
-{
- gchar *filename;
- int retval;
- gboolean ret = FALSE;
- guint32 attrs;
-#if 0
- struct stat statbuf;
- struct _WapiFileShare *shareinfo;
-#endif
-
- if(name==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- filename=mono_unicode_to_external(name);
- if(filename==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- attrs = GetFileAttributes (name);
- if (attrs == INVALID_FILE_ATTRIBUTES) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
- /* Error set by GetFileAttributes() */
- g_free (filename);
- return(FALSE);
- }
-
-#if 0
- /* Check to make sure sharing allows us to open the file for
- * writing. See bug 323389.
- *
- * Do the checks that don't need an open file descriptor, for
- * simplicity's sake. If we really have to do the full checks
- * then we can implement that later.
- */
- if (_wapi_stat (filename, &statbuf) < 0) {
- _wapi_set_last_path_error_from_errno (NULL, filename);
- g_free (filename);
- return(FALSE);
- }
-
- if (share_allows_open (&statbuf, 0, GENERIC_WRITE,
- &shareinfo) == FALSE) {
- SetLastError (ERROR_SHARING_VIOLATION);
- g_free (filename);
- return FALSE;
- }
- if (shareinfo)
- _wapi_handle_share_release (shareinfo);
-#endif
-
- retval = _wapi_unlink (filename);
-
- if (retval == -1) {
- _wapi_set_last_path_error_from_errno (NULL, filename);
- } else {
- ret = TRUE;
- }
-
- g_free(filename);
-
- return(ret);
-}
-
-/**
- * MoveFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file to be moved.
- * @dest_name: a pointer to a NULL-terminated unicode string, that is the
- * new name for the file.
- *
- * Renames file @name to @dest_name.
- * MoveFile sets ERROR_ALREADY_EXISTS if the destination exists, except
- * when it is the same file as the source. In that case it silently succeeds.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name)
-{
- gchar *utf8_name, *utf8_dest_name;
- int result, errno_copy;
- struct stat stat_src, stat_dest;
- gboolean ret = FALSE;
- struct _WapiFileShare *shareinfo;
-
- if(name==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_name = mono_unicode_to_external (name);
- if (utf8_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return FALSE;
- }
-
- if(dest_name==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- g_free (utf8_name);
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_dest_name = mono_unicode_to_external (dest_name);
- if (utf8_dest_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- g_free (utf8_name);
- SetLastError (ERROR_INVALID_NAME);
- return FALSE;
- }
-
- /*
- * In C# land we check for the existence of src, but not for dest.
- * We check it here and return the failure if dest exists and is not
- * the same file as src.
- */
- if (_wapi_stat (utf8_name, &stat_src) < 0) {
- if (errno != ENOENT || _wapi_lstat (utf8_name, &stat_src) < 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- g_free (utf8_dest_name);
- return FALSE;
- }
- }
-
- if (!_wapi_stat (utf8_dest_name, &stat_dest)) {
- if (stat_dest.st_dev != stat_src.st_dev ||
- stat_dest.st_ino != stat_src.st_ino) {
- g_free (utf8_name);
- g_free (utf8_dest_name);
- SetLastError (ERROR_ALREADY_EXISTS);
- return FALSE;
- }
- }
-
- /* Check to make that we have delete sharing permission.
- * See https://bugzilla.xamarin.com/show_bug.cgi?id=17009
- *
- * Do the checks that don't need an open file descriptor, for
- * simplicity's sake. If we really have to do the full checks
- * then we can implement that later.
- */
- if (share_allows_delete (&stat_src, &shareinfo) == FALSE) {
- SetLastError (ERROR_SHARING_VIOLATION);
- return FALSE;
- }
- if (shareinfo)
- _wapi_handle_share_release (shareinfo);
-
- result = _wapi_rename (utf8_name, utf8_dest_name);
- errno_copy = errno;
-
- if (result == -1) {
- switch(errno_copy) {
- case EEXIST:
- SetLastError (ERROR_ALREADY_EXISTS);
- break;
-
- case EXDEV:
- /* Ignore here, it is dealt with below */
- break;
-
- case ENOENT:
- /* We already know src exists. Must be dest that doesn't exist. */
- _wapi_set_last_path_error_from_errno (NULL, utf8_dest_name);
- break;
-
- default:
- _wapi_set_last_error_from_errno ();
- }
- }
-
- g_free (utf8_name);
- g_free (utf8_dest_name);
-
- if (result != 0 && errno_copy == EXDEV) {
- if (S_ISDIR (stat_src.st_mode)) {
- SetLastError (ERROR_NOT_SAME_DEVICE);
- return FALSE;
- }
- /* Try a copy to the new location, and delete the source */
- if (CopyFile (name, dest_name, TRUE)==FALSE) {
- /* CopyFile will set the error */
- return(FALSE);
- }
-
- return(DeleteFile (name));
- }
-
- if (result == 0) {
- ret = TRUE;
- }
-
- return(ret);
-}
-
-static gboolean
-write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors)
-{
- int remain, n;
- char *buf, *wbuf;
- int buf_size = st_src->st_blksize;
- MonoThreadInfo *info = mono_thread_info_current ();
-
- buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size);
- buf = (char *) g_malloc (buf_size);
-
- for (;;) {
- remain = read (src_fd, buf, buf_size);
- if (remain < 0) {
- if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
- continue;
-
- if (report_errors)
- _wapi_set_last_error_from_errno ();
-
- g_free (buf);
- return FALSE;
- }
- if (remain == 0) {
- break;
- }
-
- wbuf = buf;
- while (remain > 0) {
- if ((n = write (dest_fd, wbuf, remain)) < 0) {
- if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
- continue;
-
- if (report_errors)
- _wapi_set_last_error_from_errno ();
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write failed.", __func__);
- g_free (buf);
- return FALSE;
- }
-
- remain -= n;
- wbuf += n;
- }
- }
-
- g_free (buf);
- return TRUE ;
-}
-
-/**
- * CopyFile:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the file to be copied.
- * @dest_name: a pointer to a NULL-terminated unicode string, that is the
- * new name for the file.
- * @fail_if_exists: if TRUE and dest_name exists, the copy will fail.
- *
- * Copies file @name to @dest_name
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
- gboolean fail_if_exists)
-{
- gchar *utf8_src, *utf8_dest;
- int src_fd, dest_fd;
- struct stat st, dest_st;
- struct utimbuf dest_time;
- gboolean ret = TRUE;
- int ret_utime;
-
- if(name==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_src = mono_unicode_to_external (name);
- if (utf8_src == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of source returned NULL",
- __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- if(dest_name==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dest is NULL", __func__);
-
- g_free (utf8_src);
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_dest = mono_unicode_to_external (dest_name);
- if (utf8_dest == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of dest returned NULL",
- __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
-
- g_free (utf8_src);
-
- return(FALSE);
- }
-
- src_fd = _wapi_open (utf8_src, O_RDONLY, 0);
- if (src_fd < 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_src);
-
- g_free (utf8_src);
- g_free (utf8_dest);
-
- return(FALSE);
- }
-
- if (fstat (src_fd, &st) < 0) {
- _wapi_set_last_error_from_errno ();
-
- g_free (utf8_src);
- g_free (utf8_dest);
- close (src_fd);
-
- return(FALSE);
- }
-
- /* Before trying to open/create the dest, we need to report a 'file busy'
- * error if src and dest are actually the same file. We do the check here to take
- * advantage of the IOMAP capability */
- if (!_wapi_stat (utf8_dest, &dest_st) && st.st_dev == dest_st.st_dev &&
- st.st_ino == dest_st.st_ino) {
-
- g_free (utf8_src);
- g_free (utf8_dest);
- close (src_fd);
-
- SetLastError (ERROR_SHARING_VIOLATION);
- return (FALSE);
- }
-
- if (fail_if_exists) {
- dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_EXCL, st.st_mode);
- } else {
- /* FIXME: it kinda sucks that this code path potentially scans
- * the directory twice due to the weird SetLastError()
- * behavior. */
- dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_TRUNC, st.st_mode);
- if (dest_fd < 0) {
- /* The file does not exist, try creating it */
- dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode);
- } else {
- /* Apparently this error is set if we
- * overwrite the dest file
- */
- SetLastError (ERROR_ALREADY_EXISTS);
- }
- }
- if (dest_fd < 0) {
- _wapi_set_last_error_from_errno ();
-
- g_free (utf8_src);
- g_free (utf8_dest);
- close (src_fd);
-
- return(FALSE);
- }
-
- if (!write_file (src_fd, dest_fd, &st, TRUE))
- ret = FALSE;
-
- close (src_fd);
- close (dest_fd);
-
- dest_time.modtime = st.st_mtime;
- dest_time.actime = st.st_atime;
- ret_utime = utime (utf8_dest, &dest_time);
- if (ret_utime == -1)
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
-
- g_free (utf8_src);
- g_free (utf8_dest);
-
- return ret;
-}
-
-static gchar*
-convert_arg_to_utf8 (const gunichar2 *arg, const gchar *arg_name)
-{
- gchar *utf8_ret;
-
- if (arg == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s is NULL", __func__, arg_name);
- SetLastError (ERROR_INVALID_NAME);
- return NULL;
- }
-
- utf8_ret = mono_unicode_to_external (arg);
- if (utf8_ret == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of %s returned NULL",
- __func__, arg_name);
- SetLastError (ERROR_INVALID_PARAMETER);
- return NULL;
- }
-
- return utf8_ret;
-}
-
-gboolean
-ReplaceFile (const gunichar2 *replacedFileName, const gunichar2 *replacementFileName,
- const gunichar2 *backupFileName, guint32 replaceFlags,
- gpointer exclude, gpointer reserved)
-{
- int result, backup_fd = -1,replaced_fd = -1;
- gchar *utf8_replacedFileName, *utf8_replacementFileName = NULL, *utf8_backupFileName = NULL;
- struct stat stBackup;
- gboolean ret = FALSE;
-
- if (!(utf8_replacedFileName = convert_arg_to_utf8 (replacedFileName, "replacedFileName")))
- return FALSE;
- if (!(utf8_replacementFileName = convert_arg_to_utf8 (replacementFileName, "replacementFileName")))
- goto replace_cleanup;
- if (backupFileName != NULL) {
- if (!(utf8_backupFileName = convert_arg_to_utf8 (backupFileName, "backupFileName")))
- goto replace_cleanup;
- }
-
- if (utf8_backupFileName) {
- // Open the backup file for read so we can restore the file if an error occurs.
- backup_fd = _wapi_open (utf8_backupFileName, O_RDONLY, 0);
- result = _wapi_rename (utf8_replacedFileName, utf8_backupFileName);
- if (result == -1)
- goto replace_cleanup;
- }
-
- result = _wapi_rename (utf8_replacementFileName, utf8_replacedFileName);
- if (result == -1) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_replacementFileName);
- _wapi_rename (utf8_backupFileName, utf8_replacedFileName);
- if (backup_fd != -1 && !fstat (backup_fd, &stBackup)) {
- replaced_fd = _wapi_open (utf8_backupFileName, O_WRONLY | O_CREAT | O_TRUNC,
- stBackup.st_mode);
-
- if (replaced_fd == -1)
- goto replace_cleanup;
-
- write_file (backup_fd, replaced_fd, &stBackup, FALSE);
- }
-
- goto replace_cleanup;
- }
-
- ret = TRUE;
-
-replace_cleanup:
- g_free (utf8_replacedFileName);
- g_free (utf8_replacementFileName);
- g_free (utf8_backupFileName);
- if (backup_fd != -1)
- close (backup_fd);
- if (replaced_fd != -1)
- close (replaced_fd);
- return ret;
-}
-
-/**
- * GetStdHandle:
- * @stdhandle: specifies the file descriptor
- *
- * Returns a handle for stdin, stdout, or stderr. Always returns the
- * same handle for the same @stdhandle.
- *
- * Return value: the handle, or %INVALID_HANDLE_VALUE on error
- */
-
-static mono_mutex_t stdhandle_mutex;
-
-gpointer GetStdHandle(WapiStdHandle stdhandle)
-{
- struct _WapiHandle_file *file_handle;
- gpointer handle;
- int fd;
- const gchar *name;
- gboolean ok;
-
- switch(stdhandle) {
- case STD_INPUT_HANDLE:
- fd = 0;
- name = "<stdin>";
- break;
-
- case STD_OUTPUT_HANDLE:
- fd = 1;
- name = "<stdout>";
- break;
-
- case STD_ERROR_HANDLE:
- fd = 2;
- name = "<stderr>";
- break;
-
- default:
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unknown standard handle type", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(INVALID_HANDLE_VALUE);
- }
-
- handle = GINT_TO_POINTER (fd);
-
- mono_os_mutex_lock (&stdhandle_mutex);
-
- ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
- (gpointer *)&file_handle);
- if (ok == FALSE) {
- /* Need to create this console handle */
- handle = _wapi_stdhandle_create (fd, name);
-
- if (handle == INVALID_HANDLE_VALUE) {
- SetLastError (ERROR_NO_MORE_FILES);
- goto done;
- }
- } else {
- /* Add a reference to this handle */
- mono_w32handle_ref (handle);
- }
-
- done:
- mono_os_mutex_unlock (&stdhandle_mutex);
-
- return(handle);
-}
-
-/**
- * ReadFile:
- * @handle: The file handle to read from. The handle must have
- * %GENERIC_READ access.
- * @buffer: The buffer to store read data in
- * @numbytes: The maximum number of bytes to read
- * @bytesread: The actual number of bytes read is stored here. This
- * value can be zero if the handle is positioned at the end of the
- * file.
- * @overlapped: points to a required %WapiOverlapped structure if
- * @handle has the %FILE_FLAG_OVERLAPPED option set, should be NULL
- * otherwise.
- *
- * If @handle does not have the %FILE_FLAG_OVERLAPPED option set, this
- * function reads up to @numbytes bytes from the file from the current
- * file position, and stores them in @buffer. If there are not enough
- * bytes left in the file, just the amount available will be read.
- * The actual number of bytes read is stored in @bytesread.
-
- * If @handle has the %FILE_FLAG_OVERLAPPED option set, the current
- * file position is ignored and the read position is taken from data
- * in the @overlapped structure.
- *
- * Return value: %TRUE if the read succeeds (even if no bytes were
- * read due to an attempt to read past the end of the file), %FALSE on
- * error.
- */
-gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
- guint32 *bytesread, WapiOverlapped *overlapped)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if(io_ops[type].readfile==NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- return(io_ops[type].readfile (handle, buffer, numbytes, bytesread,
- overlapped));
-}
-
-/**
- * WriteFile:
- * @handle: The file handle to write to. The handle must have
- * %GENERIC_WRITE access.
- * @buffer: The buffer to read data from.
- * @numbytes: The maximum number of bytes to write.
- * @byteswritten: The actual number of bytes written is stored here.
- * If the handle is positioned at the file end, the length of the file
- * is extended. This parameter may be %NULL.
- * @overlapped: points to a required %WapiOverlapped structure if
- * @handle has the %FILE_FLAG_OVERLAPPED option set, should be NULL
- * otherwise.
- *
- * If @handle does not have the %FILE_FLAG_OVERLAPPED option set, this
- * function writes up to @numbytes bytes from @buffer to the file at
- * the current file position. If @handle is positioned at the end of
- * the file, the file is extended. The actual number of bytes written
- * is stored in @byteswritten.
- *
- * If @handle has the %FILE_FLAG_OVERLAPPED option set, the current
- * file position is ignored and the write position is taken from data
- * in the @overlapped structure.
- *
- * Return value: %TRUE if the write succeeds, %FALSE on error.
- */
-gboolean WriteFile(gpointer handle, gconstpointer buffer, guint32 numbytes,
- guint32 *byteswritten, WapiOverlapped *overlapped)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if(io_ops[type].writefile==NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten,
- overlapped));
-}
-
-/**
- * FlushFileBuffers:
- * @handle: Handle to open file. The handle must have
- * %GENERIC_WRITE access.
- *
- * Flushes buffers of the file and causes all unwritten data to
- * be written.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean FlushFileBuffers(gpointer handle)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if(io_ops[type].flushfile==NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- return(io_ops[type].flushfile (handle));
-}
-
-/**
- * SetEndOfFile:
- * @handle: The file handle to set. The handle must have
- * %GENERIC_WRITE access.
- *
- * Moves the end-of-file position to the current position of the file
- * pointer. This function is used to truncate or extend a file.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean SetEndOfFile(gpointer handle)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if (io_ops[type].setendoffile == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- return(io_ops[type].setendoffile (handle));
-}
-
-/**
- * SetFilePointer:
- * @handle: The file handle to set. The handle must have
- * %GENERIC_READ or %GENERIC_WRITE access.
- * @movedistance: Low 32 bits of a signed value that specifies the
- * number of bytes to move the file pointer.
- * @highmovedistance: Pointer to the high 32 bits of a signed value
- * that specifies the number of bytes to move the file pointer, or
- * %NULL.
- * @method: The starting point for the file pointer move.
- *
- * Sets the file pointer of an open file.
- *
- * The distance to move the file pointer is calculated from
- * @movedistance and @highmovedistance: If @highmovedistance is %NULL,
- * @movedistance is the 32-bit signed value; otherwise, @movedistance
- * is the low 32 bits and @highmovedistance a pointer to the high 32
- * bits of a 64 bit signed value. A positive distance moves the file
- * pointer forward from the position specified by @method; a negative
- * distance moves the file pointer backward.
- *
- * If the library is compiled without large file support,
- * @highmovedistance is ignored and its value is set to zero on a
- * successful return.
- *
- * Return value: On success, the low 32 bits of the new file pointer.
- * If @highmovedistance is not %NULL, the high 32 bits of the new file
- * pointer are stored there. On failure, %INVALID_SET_FILE_POINTER.
- */
-guint32 SetFilePointer(gpointer handle, gint32 movedistance,
- gint32 *highmovedistance, WapiSeekMethod method)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if (io_ops[type].seek == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(INVALID_SET_FILE_POINTER);
- }
-
- return(io_ops[type].seek (handle, movedistance, highmovedistance,
- method));
-}
-
-/**
- * GetFileType:
- * @handle: The file handle to test.
- *
- * Finds the type of file @handle.
- *
- * Return value: %FILE_TYPE_UNKNOWN - the type of the file @handle is
- * unknown. %FILE_TYPE_DISK - @handle is a disk file.
- * %FILE_TYPE_CHAR - @handle is a character device, such as a console.
- * %FILE_TYPE_PIPE - @handle is a named or anonymous pipe.
- */
-WapiFileType GetFileType(gpointer handle)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if (io_ops[type].getfiletype == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FILE_TYPE_UNKNOWN);
- }
-
- return(io_ops[type].getfiletype ());
-}
-
-/**
- * GetFileSize:
- * @handle: The file handle to query. The handle must have
- * %GENERIC_READ or %GENERIC_WRITE access.
- * @highsize: If non-%NULL, the high 32 bits of the file size are
- * stored here.
- *
- * Retrieves the size of the file @handle.
- *
- * If the library is compiled without large file support, @highsize
- * has its value set to zero on a successful return.
- *
- * Return value: On success, the low 32 bits of the file size. If
- * @highsize is non-%NULL then the high 32 bits of the file size are
- * stored here. On failure %INVALID_FILE_SIZE is returned.
- */
-guint32 GetFileSize(gpointer handle, guint32 *highsize)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if (io_ops[type].getfilesize == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(INVALID_FILE_SIZE);
- }
-
- return(io_ops[type].getfilesize (handle, highsize));
-}
-
-/**
- * GetFileTime:
- * @handle: The file handle to query. The handle must have
- * %GENERIC_READ access.
- * @create_time: Points to a %WapiFileTime structure to receive the
- * number of ticks since the epoch that file was created. May be
- * %NULL.
- * @last_access: Points to a %WapiFileTime structure to receive the
- * number of ticks since the epoch when file was last accessed. May be
- * %NULL.
- * @last_write: Points to a %WapiFileTime structure to receive the
- * number of ticks since the epoch when file was last written to. May
- * be %NULL.
- *
- * Finds the number of ticks since the epoch that the file referenced
- * by @handle was created, last accessed and last modified. A tick is
- * a 100 nanosecond interval. The epoch is Midnight, January 1 1601
- * GMT.
- *
- * Create time isn't recorded on POSIX file systems or reported by
- * stat(2), so that time is guessed by returning the oldest of the
- * other times.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
- WapiFileTime *last_access, WapiFileTime *last_write)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if (io_ops[type].getfiletime == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- return(io_ops[type].getfiletime (handle, create_time, last_access,
- last_write));
-}
-
-/**
- * SetFileTime:
- * @handle: The file handle to set. The handle must have
- * %GENERIC_WRITE access.
- * @create_time: Points to a %WapiFileTime structure that contains the
- * number of ticks since the epoch that the file was created. May be
- * %NULL.
- * @last_access: Points to a %WapiFileTime structure that contains the
- * number of ticks since the epoch when the file was last accessed.
- * May be %NULL.
- * @last_write: Points to a %WapiFileTime structure that contains the
- * number of ticks since the epoch when the file was last written to.
- * May be %NULL.
- *
- * Sets the number of ticks since the epoch that the file referenced
- * by @handle was created, last accessed or last modified. A tick is
- * a 100 nanosecond interval. The epoch is Midnight, January 1 1601
- * GMT.
- *
- * Create time isn't recorded on POSIX file systems, and is ignored.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time,
- const WapiFileTime *last_access,
- const WapiFileTime *last_write)
-{
- MonoW32HandleType type;
-
- type = mono_w32handle_get_type (handle);
-
- if (io_ops[type].setfiletime == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- return(io_ops[type].setfiletime (handle, create_time, last_access,
- last_write));
-}
-
-/* A tick is a 100-nanosecond interval. File time epoch is Midnight,
- * January 1 1601 GMT
- */
-
-#define TICKS_PER_MILLISECOND 10000L
-#define TICKS_PER_SECOND 10000000L
-#define TICKS_PER_MINUTE 600000000L
-#define TICKS_PER_HOUR 36000000000LL
-#define TICKS_PER_DAY 864000000000LL
-
-#define isleap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
-
-static const guint16 mon_yday[2][13]={
- {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
- {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
-};
-
-/**
- * FileTimeToSystemTime:
- * @file_time: Points to a %WapiFileTime structure that contains the
- * number of ticks to convert.
- * @system_time: Points to a %WapiSystemTime structure to receive the
- * broken-out time.
- *
- * Converts a tick count into broken-out time values.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
- WapiSystemTime *system_time)
-{
- gint64 file_ticks, totaldays, rem, y;
- const guint16 *ip;
-
- if(system_time==NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: system_time NULL", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- file_ticks=((gint64)file_time->dwHighDateTime << 32) +
- file_time->dwLowDateTime;
-
- /* Really compares if file_ticks>=0x8000000000000000
- * (LLONG_MAX+1) but we're working with a signed value for the
- * year and day calculation to work later
- */
- if(file_ticks<0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file_time too big", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- totaldays=(file_ticks / TICKS_PER_DAY);
- rem = file_ticks % TICKS_PER_DAY;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
-
- system_time->wHour=rem/TICKS_PER_HOUR;
- rem %= TICKS_PER_HOUR;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
-
- system_time->wMinute = rem / TICKS_PER_MINUTE;
- rem %= TICKS_PER_MINUTE;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
- rem);
-
- system_time->wSecond = rem / TICKS_PER_SECOND;
- rem %= TICKS_PER_SECOND;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %lld", __func__, system_time->wSecond,
- rem);
-
- system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Milliseconds: %d", __func__,
- system_time->wMilliseconds);
-
- /* January 1, 1601 was a Monday, according to Emacs calendar */
- system_time->wDayOfWeek = ((1 + totaldays) % 7) + 1;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day of week: %d", __func__, system_time->wDayOfWeek);
-
- /* This algorithm to find year and month given days from epoch
- * from glibc
- */
- y=1601;
-
-#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
-#define LEAPS_THRU_END_OF(y) (DIV(y, 4) - DIV (y, 100) + DIV (y, 400))
-
- while(totaldays < 0 || totaldays >= (isleap(y)?366:365)) {
- /* Guess a corrected year, assuming 365 days per year */
- gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld yg: %lld y: %lld", __func__,
- totaldays, yg,
- y);
- g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
- LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
-
- /* Adjust days and y to match the guessed year. */
- totaldays -= ((yg - y) * 365
- + LEAPS_THRU_END_OF (yg - 1)
- - LEAPS_THRU_END_OF (y - 1));
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
- y = yg;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y);
- }
-
- system_time->wYear = y;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Year: %d", __func__, system_time->wYear);
-
- ip = mon_yday[isleap(y)];
-
- for(y=11; totaldays < ip[y]; --y) {
- continue;
- }
- totaldays-=ip[y];
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
-
- system_time->wMonth = y + 1;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth);
-
- system_time->wDay = totaldays + 1;
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day: %d", __func__, system_time->wDay);
-
- return(TRUE);
-}
-
-gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
-{
- struct _WapiHandle_find find_handle = {0};
- gpointer handle;
- gchar *utf8_pattern = NULL, *dir_part, *entry_part;
- int result;
-
- if (pattern == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pattern is NULL", __func__);
-
- SetLastError (ERROR_PATH_NOT_FOUND);
- return(INVALID_HANDLE_VALUE);
- }
-
- utf8_pattern = mono_unicode_to_external (pattern);
- if (utf8_pattern == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(INVALID_HANDLE_VALUE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for [%s]", __func__, utf8_pattern);
-
- /* Figure out which bit of the pattern is the directory */
- dir_part = _wapi_dirname (utf8_pattern);
- entry_part = _wapi_basename (utf8_pattern);
-
-#if 0
- /* Don't do this check for now, it breaks if directories
- * really do have metachars in their names (see bug 58116).
- * FIXME: Figure out a better solution to keep some checks...
- */
- if (strchr (dir_part, '*') || strchr (dir_part, '?')) {
- SetLastError (ERROR_INVALID_NAME);
- g_free (dir_part);
- g_free (entry_part);
- g_free (utf8_pattern);
- return(INVALID_HANDLE_VALUE);
- }
-#endif
-
- /* The pattern can specify a directory or a set of files.
- *
- * The pattern can have wildcard characters ? and *, but only
- * in the section after the last directory delimiter. (Return
- * ERROR_INVALID_NAME if there are wildcards in earlier path
- * sections.) "*" has the usual 0-or-more chars meaning. "?"
- * means "match one character", "??" seems to mean "match one
- * or two characters", "???" seems to mean "match one, two or
- * three characters", etc. Windows will also try and match
- * the mangled "short name" of files, so 8 character patterns
- * with wildcards will show some surprising results.
- *
- * All the written documentation I can find says that '?'
- * should only match one character, and doesn't mention '??',
- * '???' etc. I'm going to assume that the strict behaviour
- * (ie '???' means three and only three characters) is the
- * correct one, because that lets me use fnmatch(3) rather
- * than mess around with regexes.
- */
-
- find_handle.namelist = NULL;
- result = _wapi_io_scandir (dir_part, entry_part,
- &find_handle.namelist);
-
- if (result == 0) {
- /* No files, which windows seems to call
- * FILE_NOT_FOUND
- */
- SetLastError (ERROR_FILE_NOT_FOUND);
- g_free (utf8_pattern);
- g_free (entry_part);
- g_free (dir_part);
- return (INVALID_HANDLE_VALUE);
- }
-
- if (result < 0) {
- _wapi_set_last_path_error_from_errno (dir_part, NULL);
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: scandir error: %s", __func__, g_strerror (errno));
- g_free (utf8_pattern);
- g_free (entry_part);
- g_free (dir_part);
- return (INVALID_HANDLE_VALUE);
- }
-
- g_free (utf8_pattern);
- g_free (entry_part);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Got %d matches", __func__, result);
-
- find_handle.dir_part = dir_part;
- find_handle.num = result;
- find_handle.count = 0;
-
- handle = mono_w32handle_new (MONO_W32HANDLE_FIND, &find_handle);
- if (handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating find handle", __func__);
- g_free (dir_part);
- g_free (entry_part);
- g_free (utf8_pattern);
- SetLastError (ERROR_GEN_FAILURE);
-
- return(INVALID_HANDLE_VALUE);
- }
-
- if (handle != INVALID_HANDLE_VALUE &&
- !FindNextFile (handle, find_data)) {
- FindClose (handle);
- SetLastError (ERROR_NO_MORE_FILES);
- handle = INVALID_HANDLE_VALUE;
- }
-
- return (handle);
-}
-
-gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
-{
- struct _WapiHandle_find *find_handle;
- gboolean ok;
- struct stat buf, linkbuf;
- int result;
- gchar *filename;
- gchar *utf8_filename, *utf8_basename;
- gunichar2 *utf16_basename;
- time_t create_time;
- glong bytes;
- gboolean ret = FALSE;
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
- (gpointer *)&find_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up find handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- mono_w32handle_lock_handle (handle);
-
-retry:
- if (find_handle->count >= find_handle->num) {
- SetLastError (ERROR_NO_MORE_FILES);
- goto cleanup;
- }
-
- /* stat next match */
-
- filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
-
- result = _wapi_stat (filename, &buf);
- if (result == -1 && errno == ENOENT) {
- /* Might be a dangling symlink */
- result = _wapi_lstat (filename, &buf);
- }
-
- if (result != 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: stat failed: %s", __func__, filename);
-
- g_free (filename);
- goto retry;
- }
-
-#ifndef __native_client__
- result = _wapi_lstat (filename, &linkbuf);
- if (result != 0) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
-
- g_free (filename);
- goto retry;
- }
-#endif
-
- utf8_filename = mono_utf8_from_external (filename);
- if (utf8_filename == NULL) {
- /* We couldn't turn this filename into utf8 (eg the
- * encoding of the name wasn't convertible), so just
- * ignore it.
- */
- g_warning ("%s: Bad encoding for '%s'\nConsider using MONO_EXTERNAL_ENCODINGS\n", __func__, filename);
-
- g_free (filename);
- goto retry;
- }
- g_free (filename);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Found [%s]", __func__, utf8_filename);
-
- /* fill data block */
-
- if (buf.st_mtime < buf.st_ctime)
- create_time = buf.st_mtime;
- else
- create_time = buf.st_ctime;
-
-#ifdef __native_client__
- find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL);
-#else
- find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf);
-#endif
-
- time_t_to_filetime (create_time, &find_data->ftCreationTime);
- time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
- time_t_to_filetime (buf.st_mtime, &find_data->ftLastWriteTime);
-
- if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- find_data->nFileSizeHigh = 0;
- find_data->nFileSizeLow = 0;
- } else {
- find_data->nFileSizeHigh = buf.st_size >> 32;
- find_data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
- }
-
- find_data->dwReserved0 = 0;
- find_data->dwReserved1 = 0;
-
- utf8_basename = _wapi_basename (utf8_filename);
- utf16_basename = g_utf8_to_utf16 (utf8_basename, -1, NULL, &bytes,
- NULL);
- if(utf16_basename==NULL) {
- g_free (utf8_basename);
- g_free (utf8_filename);
- goto retry;
- }
- ret = TRUE;
-
- /* utf16 is 2 * utf8 */
- bytes *= 2;
-
- memset (find_data->cFileName, '\0', (MAX_PATH*2));
-
- /* Truncating a utf16 string like this might leave the last
- * char incomplete
- */
- memcpy (find_data->cFileName, utf16_basename,
- bytes<(MAX_PATH*2)-2?bytes:(MAX_PATH*2)-2);
-
- find_data->cAlternateFileName [0] = 0; /* not used */
-
- g_free (utf8_basename);
- g_free (utf8_filename);
- g_free (utf16_basename);
-
-cleanup:
- mono_w32handle_unlock_handle (handle);
-
- return(ret);
-}
-
-/**
- * FindClose:
- * @wapi_handle: the find handle to close.
- *
- * Closes find handle @wapi_handle
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean FindClose (gpointer handle)
-{
- struct _WapiHandle_find *find_handle;
- gboolean ok;
-
- if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
- (gpointer *)&find_handle);
- if(ok==FALSE) {
- g_warning ("%s: error looking up find handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- mono_w32handle_lock_handle (handle);
-
- g_strfreev (find_handle->namelist);
- g_free (find_handle->dir_part);
-
- mono_w32handle_unlock_handle (handle);
-
- mono_w32handle_unref (handle);
-
- return(TRUE);
-}
-
-/**
- * CreateDirectory:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the directory to be created.
- * @security: ignored for now
- *
- * Creates directory @name
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean CreateDirectory (const gunichar2 *name,
- WapiSecurityAttributes *security)
-{
- gchar *utf8_name;
- int result;
-
- if (name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_name = mono_unicode_to_external (name);
- if (utf8_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return FALSE;
- }
-
- result = _wapi_mkdir (utf8_name, 0777);
-
- if (result == 0) {
- g_free (utf8_name);
- return TRUE;
- }
-
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- return FALSE;
-}
-
-/**
- * RemoveDirectory:
- * @name: a pointer to a NULL-terminated unicode string, that names
- * the directory to be removed.
- *
- * Removes directory @name
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean RemoveDirectory (const gunichar2 *name)
-{
- gchar *utf8_name;
- int result;
-
- if (name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_name = mono_unicode_to_external (name);
- if (utf8_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return FALSE;
- }
-
- result = _wapi_rmdir (utf8_name);
- if (result == -1) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
-
- return(FALSE);
- }
- g_free (utf8_name);
-
- return(TRUE);
-}
-
-/**
- * GetFileAttributes:
- * @name: a pointer to a NULL-terminated unicode filename.
- *
- * Gets the attributes for @name;
- *
- * Return value: %INVALID_FILE_ATTRIBUTES on failure
- */
-guint32 GetFileAttributes (const gunichar2 *name)
-{
- gchar *utf8_name;
- struct stat buf, linkbuf;
- int result;
- guint32 ret;
-
- if (name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_name = mono_unicode_to_external (name);
- if (utf8_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return (INVALID_FILE_ATTRIBUTES);
- }
-
- result = _wapi_stat (utf8_name, &buf);
- if (result == -1 && errno == ENOENT) {
- /* Might be a dangling symlink... */
- result = _wapi_lstat (utf8_name, &buf);
- }
-
- if (result != 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- return (INVALID_FILE_ATTRIBUTES);
- }
-
-#ifndef __native_client__
- result = _wapi_lstat (utf8_name, &linkbuf);
- if (result != 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- return (INVALID_FILE_ATTRIBUTES);
- }
-#endif
-
-#ifdef __native_client__
- ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL);
-#else
- ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
-#endif
-
- g_free (utf8_name);
-
- return(ret);
-}
-
-/**
- * GetFileAttributesEx:
- * @name: a pointer to a NULL-terminated unicode filename.
- * @level: must be GetFileExInfoStandard
- * @info: pointer to a WapiFileAttributesData structure
- *
- * Gets attributes, size and filetimes for @name;
- *
- * Return value: %TRUE on success, %FALSE on failure
- */
-gboolean GetFileAttributesEx (const gunichar2 *name, WapiGetFileExInfoLevels level, gpointer info)
-{
- gchar *utf8_name;
- WapiFileAttributesData *data;
-
- struct stat buf, linkbuf;
- time_t create_time;
- int result;
-
- if (level != GetFileExInfoStandard) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: info level %d not supported.", __func__,
- level);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- if (name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_name = mono_unicode_to_external (name);
- if (utf8_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- result = _wapi_stat (utf8_name, &buf);
- if (result == -1 && errno == ENOENT) {
- /* Might be a dangling symlink... */
- result = _wapi_lstat (utf8_name, &buf);
- }
-
- if (result != 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- return FALSE;
- }
-
- result = _wapi_lstat (utf8_name, &linkbuf);
- if (result != 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- return(FALSE);
- }
-
- /* fill data block */
-
- data = (WapiFileAttributesData *)info;
-
- if (buf.st_mtime < buf.st_ctime)
- create_time = buf.st_mtime;
- else
- create_time = buf.st_ctime;
-
- data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_name,
- &buf,
- &linkbuf);
-
- g_free (utf8_name);
-
- time_t_to_filetime (create_time, &data->ftCreationTime);
- time_t_to_filetime (buf.st_atime, &data->ftLastAccessTime);
- time_t_to_filetime (buf.st_mtime, &data->ftLastWriteTime);
-
- if (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
- data->nFileSizeHigh = 0;
- data->nFileSizeLow = 0;
- }
- else {
- data->nFileSizeHigh = buf.st_size >> 32;
- data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
- }
-
- return TRUE;
-}
-
-/**
- * SetFileAttributes
- * @name: name of file
- * @attrs: attributes to set
- *
- * Changes the attributes on a named file.
- *
- * Return value: %TRUE on success, %FALSE on failure.
- */
-extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs)
-{
- /* FIXME: think of something clever to do on unix */
- gchar *utf8_name;
- struct stat buf;
- int result;
-
- /*
- * Currently we only handle one *internal* case, with a value that is
- * not standard: 0x80000000, which means `set executable bit'
- */
-
- if (name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
-
- utf8_name = mono_unicode_to_external (name);
- if (utf8_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return FALSE;
- }
-
- result = _wapi_stat (utf8_name, &buf);
- if (result == -1 && errno == ENOENT) {
- /* Might be a dangling symlink... */
- result = _wapi_lstat (utf8_name, &buf);
- }
-
- if (result != 0) {
- _wapi_set_last_path_error_from_errno (NULL, utf8_name);
- g_free (utf8_name);
- return FALSE;
- }
-
- /* Contrary to the documentation, ms allows NORMAL to be
- * specified along with other attributes, so dont bother to
- * catch that case here.
- */
- if (attrs & FILE_ATTRIBUTE_READONLY) {
- result = _wapi_chmod (utf8_name, buf.st_mode & ~(S_IWUSR | S_IWOTH | S_IWGRP));
- } else {
- result = _wapi_chmod (utf8_name, buf.st_mode | S_IWUSR);
- }
-
- /* Ignore the other attributes for now */
-
- if (attrs & 0x80000000){
- mode_t exec_mask = 0;
-
- if ((buf.st_mode & S_IRUSR) != 0)
- exec_mask |= S_IXUSR;
-
- if ((buf.st_mode & S_IRGRP) != 0)
- exec_mask |= S_IXGRP;
-
- if ((buf.st_mode & S_IROTH) != 0)
- exec_mask |= S_IXOTH;
-
- result = chmod (utf8_name, buf.st_mode | exec_mask);
- }
- /* Don't bother to reset executable (might need to change this
- * policy)
- */
-
- g_free (utf8_name);
-
- return(TRUE);
-}
-
-/**
- * GetCurrentDirectory
- * @length: size of the buffer
- * @buffer: pointer to buffer that recieves path
- *
- * Retrieves the current directory for the current process.
- *
- * Return value: number of characters in buffer on success, zero on failure
- */
-extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer)
-{
- gunichar2 *utf16_path;
- glong count;
- gsize bytes;
-
-#ifdef __native_client__
- gchar *path = g_get_current_dir ();
- if (length < strlen(path) + 1 || path == NULL)
- return 0;
- memcpy (buffer, path, strlen(path) + 1);
-#else
- if (getcwd ((char*)buffer, length) == NULL) {
- if (errno == ERANGE) { /*buffer length is not big enough */
- gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/
- if (path == NULL)
- return 0;
- utf16_path = mono_unicode_from_external (path, &bytes);
- g_free (utf16_path);
- g_free (path);
- return (bytes/2)+1;
- }
- _wapi_set_last_error_from_errno ();
- return 0;
- }
-#endif
-
- utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
- count = (bytes/2)+1;
- g_assert (count <= length); /*getcwd must have failed before with ERANGE*/
-
- /* Add the terminator */
- memset (buffer, '\0', bytes+2);
- memcpy (buffer, utf16_path, bytes);
-
- g_free (utf16_path);
-
- return count;
-}
-
-/**
- * SetCurrentDirectory
- * @path: path to new directory
- *
- * Changes the directory path for the current process.
- *
- * Return value: %TRUE on success, %FALSE on failure.
- */
-extern gboolean SetCurrentDirectory (const gunichar2 *path)
-{
- gchar *utf8_path;
- gboolean result;
-
- if (path == NULL) {
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- utf8_path = mono_unicode_to_external (path);
- if (_wapi_chdir (utf8_path) != 0) {
- _wapi_set_last_error_from_errno ();
- result = FALSE;
- }
- else
- result = TRUE;
-
- g_free (utf8_path);
- return result;
-}
-
-gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
- WapiSecurityAttributes *security G_GNUC_UNUSED, guint32 size)
-{
- struct _WapiHandle_file pipe_read_handle = {0};
- struct _WapiHandle_file pipe_write_handle = {0};
- gpointer read_handle;
- gpointer write_handle;
- int filedes[2];
- int ret;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
-
- ret=pipe (filedes);
- if(ret==-1) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
- strerror (errno));
-
- _wapi_set_last_error_from_errno ();
- return(FALSE);
- }
-
- if (filedes[0] >= mono_w32handle_fd_reserve ||
- filedes[1] >= mono_w32handle_fd_reserve) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
-
- SetLastError (ERROR_TOO_MANY_OPEN_FILES);
-
- close (filedes[0]);
- close (filedes[1]);
-
- return(FALSE);
- }
-
- /* filedes[0] is open for reading, filedes[1] for writing */
-
- pipe_read_handle.fd = filedes [0];
- pipe_read_handle.fileaccess = GENERIC_READ;
- read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0],
- &pipe_read_handle);
- if (read_handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating pipe read handle", __func__);
- close (filedes[0]);
- close (filedes[1]);
- SetLastError (ERROR_GEN_FAILURE);
-
- return(FALSE);
- }
-
- pipe_write_handle.fd = filedes [1];
- pipe_write_handle.fileaccess = GENERIC_WRITE;
- write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1],
- &pipe_write_handle);
- if (write_handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating pipe write handle", __func__);
- mono_w32handle_unref (read_handle);
-
- close (filedes[0]);
- close (filedes[1]);
- SetLastError (ERROR_GEN_FAILURE);
-
- return(FALSE);
- }
-
- *readpipe = read_handle;
- *writepipe = write_handle;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p",
- __func__, read_handle, write_handle);
-
- return(TRUE);
-}
-
-#ifdef HAVE_GETFSSTAT
-/* Darwin has getfsstat */
-gint32 GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
-{
- struct statfs *stats;
- int size, n, i;
- gunichar2 *dir;
- glong length, total = 0;
-
- n = getfsstat (NULL, 0, MNT_NOWAIT);
- if (n == -1)
- return 0;
- size = n * sizeof (struct statfs);
- stats = (struct statfs *) g_malloc (size);
- if (stats == NULL)
- return 0;
- if (getfsstat (stats, size, MNT_NOWAIT) == -1){
- g_free (stats);
- return 0;
- }
- for (i = 0; i < n; i++){
- dir = g_utf8_to_utf16 (stats [i].f_mntonname, -1, NULL, &length, NULL);
- if (total + length < len){
- memcpy (buf + total, dir, sizeof (gunichar2) * length);
- buf [total+length] = 0;
- }
- g_free (dir);
- total += length + 1;
- }
- if (total < len)
- buf [total] = 0;
- total++;
- g_free (stats);
- return total;
-}
-#else
-/* In-place octal sequence replacement */
-static void
-unescape_octal (gchar *str)
-{
- gchar *rptr;
- gchar *wptr;
-
- if (str == NULL)
- return;
-
- rptr = wptr = str;
- while (*rptr != '\0') {
- if (*rptr == '\\') {
- char c;
- rptr++;
- c = (*(rptr++) - '0') << 6;
- c += (*(rptr++) - '0') << 3;
- c += *(rptr++) - '0';
- *wptr++ = c;
- } else if (wptr != rptr) {
- *wptr++ = *rptr++;
- } else {
- rptr++; wptr++;
- }
- }
- *wptr = '\0';
-}
-static gint32 GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf);
-
-#if __linux__
-#define GET_LOGICAL_DRIVE_STRINGS_BUFFER 512
-#define GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER 512
-#define GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER 64
-
-typedef struct
-{
- glong total;
- guint32 buffer_index;
- guint32 mountpoint_index;
- guint32 field_number;
- guint32 allocated_size;
- guint32 fsname_index;
- guint32 fstype_index;
- gchar mountpoint [GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER + 1];
- gchar *mountpoint_allocated;
- gchar buffer [GET_LOGICAL_DRIVE_STRINGS_BUFFER];
- gchar fsname [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
- gchar fstype [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
- ssize_t nbytes;
- gchar delimiter;
- gboolean check_mount_source;
-} LinuxMountInfoParseState;
-
-static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
-static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
-static void append_to_mountpoint (LinuxMountInfoParseState *state);
-static gboolean add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
-
-gint32 GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
-{
- int fd;
- gint32 ret = 0;
- LinuxMountInfoParseState state;
- gboolean (*parser)(guint32, gunichar2*, LinuxMountInfoParseState*) = NULL;
-
- memset (buf, 0, len * sizeof (gunichar2));
- fd = open ("/proc/self/mountinfo", O_RDONLY);
- if (fd != -1)
- parser = GetLogicalDriveStrings_MountInfo;
- else {
- fd = open ("/proc/mounts", O_RDONLY);
- if (fd != -1)
- parser = GetLogicalDriveStrings_Mounts;
- }
-
- if (!parser) {
- ret = GetLogicalDriveStrings_Mtab (len, buf);
- goto done_and_out;
- }
-
- memset (&state, 0, sizeof (LinuxMountInfoParseState));
- state.field_number = 1;
- state.delimiter = ' ';
-
- while ((state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER)) > 0) {
- state.buffer_index = 0;
-
- while ((*parser)(len, buf, &state)) {
- if (state.buffer [state.buffer_index] == '\n') {
- gboolean quit = add_drive_string (len, buf, &state);
- state.field_number = 1;
- state.buffer_index++;
- if (state.mountpoint_allocated) {
- g_free (state.mountpoint_allocated);
- state.mountpoint_allocated = NULL;
- }
- if (quit) {
- ret = state.total;
- goto done_and_out;
- }
- }
- }
- };
- ret = state.total;
-
- done_and_out:
- if (fd != -1)
- close (fd);
- return ret;
-}
-
-static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
-{
- gchar *ptr;
-
- if (state->field_number == 1)
- state->check_mount_source = TRUE;
-
- while (state->buffer_index < (guint32)state->nbytes) {
- if (state->buffer [state->buffer_index] == state->delimiter) {
- state->field_number++;
- switch (state->field_number) {
- case 2:
- state->mountpoint_index = 0;
- break;
-
- case 3:
- if (state->mountpoint_allocated)
- state->mountpoint_allocated [state->mountpoint_index] = 0;
- else
- state->mountpoint [state->mountpoint_index] = 0;
- break;
-
- default:
- ptr = (gchar*)memchr (state->buffer + state->buffer_index, '\n', GET_LOGICAL_DRIVE_STRINGS_BUFFER - state->buffer_index);
- if (ptr)
- state->buffer_index = (ptr - (gchar*)state->buffer) - 1;
- else
- state->buffer_index = state->nbytes;
- return TRUE;
- }
- state->buffer_index++;
- continue;
- } else if (state->buffer [state->buffer_index] == '\n')
- return TRUE;
-
- switch (state->field_number) {
- case 1:
- if (state->check_mount_source) {
- if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
- /* We can ignore the rest, it's a device
- * path */
- state->check_mount_source = FALSE;
- state->fsname [state->fsname_index++] = '/';
- break;
- }
- if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
- state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
- }
- break;
-
- case 2:
- append_to_mountpoint (state);
- break;
-
- case 3:
- if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
- state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
- break;
- }
-
- state->buffer_index++;
- }
-
- return FALSE;
-}
-
-static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
-{
- while (state->buffer_index < (guint32)state->nbytes) {
- if (state->buffer [state->buffer_index] == state->delimiter) {
- state->field_number++;
- switch (state->field_number) {
- case 5:
- state->mountpoint_index = 0;
- break;
-
- case 6:
- if (state->mountpoint_allocated)
- state->mountpoint_allocated [state->mountpoint_index] = 0;
- else
- state->mountpoint [state->mountpoint_index] = 0;
- break;
-
- case 7:
- state->delimiter = '-';
- break;
-
- case 8:
- state->delimiter = ' ';
- break;
-
- case 10:
- state->check_mount_source = TRUE;
- break;
- }
- state->buffer_index++;
- continue;
- } else if (state->buffer [state->buffer_index] == '\n')
- return TRUE;
-
- switch (state->field_number) {
- case 5:
- append_to_mountpoint (state);
- break;
-
- case 9:
- if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
- state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
- break;
-
- case 10:
- if (state->check_mount_source) {
- if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
- /* We can ignore the rest, it's a device
- * path */
- state->check_mount_source = FALSE;
- state->fsname [state->fsname_index++] = '/';
- break;
- }
- if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
- state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
- }
- break;
- }
-
- state->buffer_index++;
- }
-
- return FALSE;
-}
-
-static void
-append_to_mountpoint (LinuxMountInfoParseState *state)
-{
- gchar ch = state->buffer [state->buffer_index];
- if (state->mountpoint_allocated) {
- if (state->mountpoint_index >= state->allocated_size) {
- guint32 newsize = (state->allocated_size << 1) + 1;
- gchar *newbuf = (gchar *)g_malloc0 (newsize * sizeof (gchar));
-
- memcpy (newbuf, state->mountpoint_allocated, state->mountpoint_index);
- g_free (state->mountpoint_allocated);
- state->mountpoint_allocated = newbuf;
- state->allocated_size = newsize;
- }
- state->mountpoint_allocated [state->mountpoint_index++] = ch;
- } else {
- if (state->mountpoint_index >= GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER) {
- state->allocated_size = (state->mountpoint_index << 1) + 1;
- state->mountpoint_allocated = (gchar *)g_malloc0 (state->allocated_size * sizeof (gchar));
- memcpy (state->mountpoint_allocated, state->mountpoint, state->mountpoint_index);
- state->mountpoint_allocated [state->mountpoint_index++] = ch;
- } else
- state->mountpoint [state->mountpoint_index++] = ch;
- }
-}
-
-static gboolean
-add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
-{
- gboolean quit = FALSE;
- gboolean ignore_entry;
-
- if (state->fsname_index == 1 && state->fsname [0] == '/')
- ignore_entry = FALSE;
- else if (memcmp ("overlay", state->fsname, state->fsname_index) == 0 ||
- memcmp ("aufs", state->fstype, state->fstype_index) == 0) {
- /* Don't ignore overlayfs and aufs - these might be used on Docker
- * (https://bugzilla.xamarin.com/show_bug.cgi?id=31021) */
- ignore_entry = FALSE;
- } else if (state->fsname_index == 0 || memcmp ("none", state->fsname, state->fsname_index) == 0) {
- ignore_entry = TRUE;
- } else if (state->fstype_index >= 5 && memcmp ("fuse.", state->fstype, 5) == 0) {
- /* Ignore GNOME's gvfs */
- if (state->fstype_index == 21 && memcmp ("fuse.gvfs-fuse-daemon", state->fstype, state->fstype_index) == 0)
- ignore_entry = TRUE;
- else
- ignore_entry = FALSE;
- } else if (state->fstype_index == 3 && memcmp ("nfs", state->fstype, state->fstype_index) == 0)
- ignore_entry = FALSE;
- else
- ignore_entry = TRUE;
-
- if (!ignore_entry) {
- gunichar2 *dir;
- glong length;
- gchar *mountpoint = state->mountpoint_allocated ? state->mountpoint_allocated : state->mountpoint;
-
- unescape_octal (mountpoint);
- dir = g_utf8_to_utf16 (mountpoint, -1, NULL, &length, NULL);
- if (state->total + length + 1 > len) {
- quit = TRUE;
- state->total = len * 2;
- } else {
- length++;
- memcpy (buf + state->total, dir, sizeof (gunichar2) * length);
- state->total += length;
- }
- g_free (dir);
- }
- state->fsname_index = 0;
- state->fstype_index = 0;
-
- return quit;
-}
-#else
-gint32
-GetLogicalDriveStrings (guint32 len, gunichar2 *buf)
-{
- return GetLogicalDriveStrings_Mtab (len, buf);
-}
-#endif
-static gint32
-GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
-{
- FILE *fp;
- gunichar2 *ptr, *dir;
- glong length, total = 0;
- gchar buffer [512];
- gchar **splitted;
-
- memset (buf, 0, sizeof (gunichar2) * (len + 1));
- buf [0] = '/';
- buf [1] = 0;
- buf [2] = 0;
-
- /* Sigh, mntent and friends don't work well.
- * It stops on the first line that doesn't begin with a '/'.
- * (linux 2.6.5, libc 2.3.2.ds1-12) - Gonz */
- fp = fopen ("/etc/mtab", "rt");
- if (fp == NULL) {
- fp = fopen ("/etc/mnttab", "rt");
- if (fp == NULL)
- return 1;
- }
-
- ptr = buf;
- while (fgets (buffer, 512, fp) != NULL) {
- if (*buffer != '/')
- continue;
-
- splitted = g_strsplit (buffer, " ", 0);
- if (!*splitted || !*(splitted + 1)) {
- g_strfreev (splitted);
- continue;
- }
-
- unescape_octal (*(splitted + 1));
- dir = g_utf8_to_utf16 (*(splitted + 1), -1, NULL, &length, NULL);
- g_strfreev (splitted);
- if (total + length + 1 > len) {
- fclose (fp);
- g_free (dir);
- return len * 2; /* guess */
- }
-
- memcpy (ptr + total, dir, sizeof (gunichar2) * length);
- g_free (dir);
- total += length + 1;
- }
-
- fclose (fp);
- return total;
-/* Commented out, does not work with my mtab!!! - Gonz */
-#ifdef NOTENABLED /* HAVE_MNTENT_H */
-{
- FILE *fp;
- struct mntent *mnt;
- gunichar2 *ptr, *dir;
- glong len, total = 0;
-
-
- fp = setmntent ("/etc/mtab", "rt");
- if (fp == NULL) {
- fp = setmntent ("/etc/mnttab", "rt");
- if (fp == NULL)
- return;
- }
-
- ptr = buf;
- while ((mnt = getmntent (fp)) != NULL) {
- g_print ("GOT %s\n", mnt->mnt_dir);
- dir = g_utf8_to_utf16 (mnt->mnt_dir, &len, NULL, NULL, NULL);
- if (total + len + 1 > len) {
- return len * 2; /* guess */
- }
-
- memcpy (ptr + total, dir, sizeof (gunichar2) * len);
- g_free (dir);
- total += len + 1;
- }
-
- endmntent (fp);
- return total;
-}
-#endif
-}
-#endif
-
-#if defined(HAVE_STATVFS) || defined(HAVE_STATFS)
-gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, ULARGE_INTEGER *free_bytes_avail,
- ULARGE_INTEGER *total_number_of_bytes,
- ULARGE_INTEGER *total_number_of_free_bytes)
-{
-#ifdef HAVE_STATVFS
- struct statvfs fsstat;
-#elif defined(HAVE_STATFS)
- struct statfs fsstat;
-#endif
- gboolean isreadonly;
- gchar *utf8_path_name;
- int ret;
- unsigned long block_size;
-
- if (path_name == NULL) {
- utf8_path_name = g_strdup (g_get_current_dir());
- if (utf8_path_name == NULL) {
- SetLastError (ERROR_DIRECTORY);
- return(FALSE);
- }
- }
- else {
- utf8_path_name = mono_unicode_to_external (path_name);
- if (utf8_path_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
-
- SetLastError (ERROR_INVALID_NAME);
- return(FALSE);
- }
- }
-
- do {
-#ifdef HAVE_STATVFS
- ret = statvfs (utf8_path_name, &fsstat);
- isreadonly = ((fsstat.f_flag & ST_RDONLY) == ST_RDONLY);
- block_size = fsstat.f_frsize;
-#elif defined(HAVE_STATFS)
- ret = statfs (utf8_path_name, &fsstat);
-#if defined (MNT_RDONLY)
- isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY);
-#elif defined (MS_RDONLY)
- isreadonly = ((fsstat.f_flags & MS_RDONLY) == MS_RDONLY);
-#endif
- block_size = fsstat.f_bsize;
-#endif
- } while(ret == -1 && errno == EINTR);
-
- g_free(utf8_path_name);
-
- if (ret == -1) {
- _wapi_set_last_error_from_errno ();
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno));
- return(FALSE);
- }
-
- /* total number of free bytes for non-root */
- if (free_bytes_avail != NULL) {
- if (isreadonly) {
- free_bytes_avail->QuadPart = 0;
- }
- else {
- free_bytes_avail->QuadPart = block_size * (guint64)fsstat.f_bavail;
- }
- }
-
- /* total number of bytes available for non-root */
- if (total_number_of_bytes != NULL) {
- total_number_of_bytes->QuadPart = block_size * (guint64)fsstat.f_blocks;
- }
-
- /* total number of bytes available for root */
- if (total_number_of_free_bytes != NULL) {
- if (isreadonly) {
- total_number_of_free_bytes->QuadPart = 0;
- }
- else {
- total_number_of_free_bytes->QuadPart = block_size * (guint64)fsstat.f_bfree;
- }
- }
-
- return(TRUE);
-}
-#else
-gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, ULARGE_INTEGER *free_bytes_avail,
- ULARGE_INTEGER *total_number_of_bytes,
- ULARGE_INTEGER *total_number_of_free_bytes)
-{
- if (free_bytes_avail != NULL) {
- free_bytes_avail->QuadPart = (guint64) -1;
- }
-
- if (total_number_of_bytes != NULL) {
- total_number_of_bytes->QuadPart = (guint64) -1;
- }
-
- if (total_number_of_free_bytes != NULL) {
- total_number_of_free_bytes->QuadPart = (guint64) -1;
- }
-
- return(TRUE);
-}
-#endif
-
-/*
- * General Unix support
- */
-typedef struct {
- guint32 drive_type;
-#if __linux__
- const long fstypeid;
-#endif
- const gchar* fstype;
-} _wapi_drive_type;
-
-static _wapi_drive_type _wapi_drive_types[] = {
-#if PLATFORM_MACOSX
- { DRIVE_REMOTE, "afp" },
- { DRIVE_REMOTE, "autofs" },
- { DRIVE_CDROM, "cddafs" },
- { DRIVE_CDROM, "cd9660" },
- { DRIVE_RAMDISK, "devfs" },
- { DRIVE_FIXED, "exfat" },
- { DRIVE_RAMDISK, "fdesc" },
- { DRIVE_REMOTE, "ftp" },
- { DRIVE_FIXED, "hfs" },
- { DRIVE_FIXED, "msdos" },
- { DRIVE_REMOTE, "nfs" },
- { DRIVE_FIXED, "ntfs" },
- { DRIVE_REMOTE, "smbfs" },
- { DRIVE_FIXED, "udf" },
- { DRIVE_REMOTE, "webdav" },
- { DRIVE_UNKNOWN, NULL }
-#elif __linux__
- { DRIVE_FIXED, ADFS_SUPER_MAGIC, "adfs"},
- { DRIVE_FIXED, AFFS_SUPER_MAGIC, "affs"},
- { DRIVE_REMOTE, AFS_SUPER_MAGIC, "afs"},
- { DRIVE_RAMDISK, AUTOFS_SUPER_MAGIC, "autofs"},
- { DRIVE_RAMDISK, AUTOFS_SBI_MAGIC, "autofs4"},
- { DRIVE_REMOTE, CODA_SUPER_MAGIC, "coda" },
- { DRIVE_RAMDISK, CRAMFS_MAGIC, "cramfs"},
- { DRIVE_RAMDISK, CRAMFS_MAGIC_WEND, "cramfs"},
- { DRIVE_REMOTE, CIFS_MAGIC_NUMBER, "cifs"},
- { DRIVE_RAMDISK, DEBUGFS_MAGIC, "debugfs"},
- { DRIVE_RAMDISK, SYSFS_MAGIC, "sysfs"},
- { DRIVE_RAMDISK, SECURITYFS_MAGIC, "securityfs"},
- { DRIVE_RAMDISK, SELINUX_MAGIC, "selinuxfs"},
- { DRIVE_RAMDISK, RAMFS_MAGIC, "ramfs"},
- { DRIVE_FIXED, SQUASHFS_MAGIC, "squashfs"},
- { DRIVE_FIXED, EFS_SUPER_MAGIC, "efs"},
- { DRIVE_FIXED, EXT2_SUPER_MAGIC, "ext"},
- { DRIVE_FIXED, EXT3_SUPER_MAGIC, "ext"},
- { DRIVE_FIXED, EXT4_SUPER_MAGIC, "ext"},
- { DRIVE_REMOTE, XENFS_SUPER_MAGIC, "xenfs"},
- { DRIVE_FIXED, BTRFS_SUPER_MAGIC, "btrfs"},
- { DRIVE_FIXED, HFS_SUPER_MAGIC, "hfs"},
- { DRIVE_FIXED, HFSPLUS_SUPER_MAGIC, "hfsplus"},
- { DRIVE_FIXED, HPFS_SUPER_MAGIC, "hpfs"},
- { DRIVE_RAMDISK, HUGETLBFS_MAGIC, "hugetlbfs"},
- { DRIVE_CDROM, ISOFS_SUPER_MAGIC, "iso"},
- { DRIVE_FIXED, JFFS2_SUPER_MAGIC, "jffs2"},
- { DRIVE_RAMDISK, ANON_INODE_FS_MAGIC, "anon_inode"},
- { DRIVE_FIXED, JFS_SUPER_MAGIC, "jfs"},
- { DRIVE_FIXED, MINIX_SUPER_MAGIC, "minix"},
- { DRIVE_FIXED, MINIX_SUPER_MAGIC2, "minix v2"},
- { DRIVE_FIXED, MINIX2_SUPER_MAGIC, "minix2"},
- { DRIVE_FIXED, MINIX2_SUPER_MAGIC2, "minix2 v2"},
- { DRIVE_FIXED, MINIX3_SUPER_MAGIC, "minix3"},
- { DRIVE_FIXED, MSDOS_SUPER_MAGIC, "msdos"},
- { DRIVE_REMOTE, NCP_SUPER_MAGIC, "ncp"},
- { DRIVE_REMOTE, NFS_SUPER_MAGIC, "nfs"},
- { DRIVE_FIXED, NTFS_SB_MAGIC, "ntfs"},
- { DRIVE_RAMDISK, OPENPROM_SUPER_MAGIC, "openpromfs"},
- { DRIVE_RAMDISK, PROC_SUPER_MAGIC, "proc"},
- { DRIVE_FIXED, QNX4_SUPER_MAGIC, "qnx4"},
- { DRIVE_FIXED, REISERFS_SUPER_MAGIC, "reiserfs"},
- { DRIVE_RAMDISK, ROMFS_MAGIC, "romfs"},
- { DRIVE_REMOTE, SMB_SUPER_MAGIC, "samba"},
- { DRIVE_RAMDISK, CGROUP_SUPER_MAGIC, "cgroupfs"},
- { DRIVE_RAMDISK, FUTEXFS_SUPER_MAGIC, "futexfs"},
- { DRIVE_FIXED, SYSV2_SUPER_MAGIC, "sysv2"},
- { DRIVE_FIXED, SYSV4_SUPER_MAGIC, "sysv4"},
- { DRIVE_RAMDISK, TMPFS_MAGIC, "tmpfs"},
- { DRIVE_RAMDISK, DEVPTS_SUPER_MAGIC, "devpts"},
- { DRIVE_CDROM, UDF_SUPER_MAGIC, "udf"},
- { DRIVE_FIXED, UFS_MAGIC, "ufs"},
- { DRIVE_FIXED, UFS_MAGIC_BW, "ufs"},
- { DRIVE_FIXED, UFS2_MAGIC, "ufs2"},
- { DRIVE_FIXED, UFS_CIGAM, "ufs"},
- { DRIVE_RAMDISK, USBDEVICE_SUPER_MAGIC, "usbdev"},
- { DRIVE_FIXED, XENIX_SUPER_MAGIC, "xenix"},
- { DRIVE_FIXED, XFS_SB_MAGIC, "xfs"},
- { DRIVE_RAMDISK, FUSE_SUPER_MAGIC, "fuse"},
- { DRIVE_FIXED, V9FS_MAGIC, "9p"},
- { DRIVE_REMOTE, CEPH_SUPER_MAGIC, "ceph"},
- { DRIVE_RAMDISK, CONFIGFS_MAGIC, "configfs"},
- { DRIVE_RAMDISK, ECRYPTFS_SUPER_MAGIC, "eCryptfs"},
- { DRIVE_FIXED, EXOFS_SUPER_MAGIC, "exofs"},
- { DRIVE_FIXED, VXFS_SUPER_MAGIC, "vxfs"},
- { DRIVE_FIXED, VXFS_OLT_MAGIC, "vxfs_olt"},
- { DRIVE_REMOTE, GFS2_MAGIC, "gfs2"},
- { DRIVE_FIXED, LOGFS_MAGIC_U32, "logfs"},
- { DRIVE_FIXED, OCFS2_SUPER_MAGIC, "ocfs2"},
- { DRIVE_FIXED, OMFS_MAGIC, "omfs"},
- { DRIVE_FIXED, UBIFS_SUPER_MAGIC, "ubifs"},
- { DRIVE_UNKNOWN, 0, NULL}
-#else
- { DRIVE_RAMDISK, "ramfs" },
- { DRIVE_RAMDISK, "tmpfs" },
- { DRIVE_RAMDISK, "proc" },
- { DRIVE_RAMDISK, "sysfs" },
- { DRIVE_RAMDISK, "debugfs" },
- { DRIVE_RAMDISK, "devpts" },
- { DRIVE_RAMDISK, "securityfs" },
- { DRIVE_CDROM, "iso9660" },
- { DRIVE_FIXED, "ext2" },
- { DRIVE_FIXED, "ext3" },
- { DRIVE_FIXED, "ext4" },
- { DRIVE_FIXED, "sysv" },
- { DRIVE_FIXED, "reiserfs" },
- { DRIVE_FIXED, "ufs" },
- { DRIVE_FIXED, "vfat" },
- { DRIVE_FIXED, "msdos" },
- { DRIVE_FIXED, "udf" },
- { DRIVE_FIXED, "hfs" },
- { DRIVE_FIXED, "hpfs" },
- { DRIVE_FIXED, "qnx4" },
- { DRIVE_FIXED, "ntfs" },
- { DRIVE_FIXED, "ntfs-3g" },
- { DRIVE_REMOTE, "smbfs" },
- { DRIVE_REMOTE, "fuse" },
- { DRIVE_REMOTE, "nfs" },
- { DRIVE_REMOTE, "nfs4" },
- { DRIVE_REMOTE, "cifs" },
- { DRIVE_REMOTE, "ncpfs" },
- { DRIVE_REMOTE, "coda" },
- { DRIVE_REMOTE, "afs" },
- { DRIVE_UNKNOWN, NULL }
-#endif
-};
-
-#if __linux__
-static guint32 _wapi_get_drive_type(long f_type)
-{
- _wapi_drive_type *current;
-
- current = &_wapi_drive_types[0];
- while (current->drive_type != DRIVE_UNKNOWN) {
- if (current->fstypeid == f_type)
- return current->drive_type;
- current++;
- }
-
- return DRIVE_UNKNOWN;
-}
-#else
-static guint32 _wapi_get_drive_type(const gchar* fstype)
-{
- _wapi_drive_type *current;
-
- current = &_wapi_drive_types[0];
- while (current->drive_type != DRIVE_UNKNOWN) {
- if (strcmp (current->fstype, fstype) == 0)
- break;
-
- current++;
- }
-
- return current->drive_type;
-}
-#endif
-
-#if defined (PLATFORM_MACOSX) || defined (__linux__)
-static guint32
-GetDriveTypeFromPath (const char *utf8_root_path_name)
-{
- struct statfs buf;
-
- if (statfs (utf8_root_path_name, &buf) == -1)
- return DRIVE_UNKNOWN;
-#if PLATFORM_MACOSX
- return _wapi_get_drive_type (buf.f_fstypename);
-#else
- return _wapi_get_drive_type (buf.f_type);
-#endif
-}
-#else
-static guint32
-GetDriveTypeFromPath (const gchar *utf8_root_path_name)
-{
- guint32 drive_type;
- FILE *fp;
- gchar buffer [512];
- gchar **splitted;
-
- fp = fopen ("/etc/mtab", "rt");
- if (fp == NULL) {
- fp = fopen ("/etc/mnttab", "rt");
- if (fp == NULL)
- return(DRIVE_UNKNOWN);
- }
-
- drive_type = DRIVE_NO_ROOT_DIR;
- while (fgets (buffer, 512, fp) != NULL) {
- splitted = g_strsplit (buffer, " ", 0);
- if (!*splitted || !*(splitted + 1) || !*(splitted + 2)) {
- g_strfreev (splitted);
- continue;
- }
-
- /* compare given root_path_name with the one from mtab,
- if length of utf8_root_path_name is zero it must be the root dir */
- if (strcmp (*(splitted + 1), utf8_root_path_name) == 0 ||
- (strcmp (*(splitted + 1), "/") == 0 && strlen (utf8_root_path_name) == 0)) {
- drive_type = _wapi_get_drive_type (*(splitted + 2));
- /* it is possible this path might be mounted again with
- a known type...keep looking */
- if (drive_type != DRIVE_UNKNOWN) {
- g_strfreev (splitted);
- break;
- }
- }
-
- g_strfreev (splitted);
- }
-
- fclose (fp);
- return drive_type;
-}
-#endif
-
-guint32 GetDriveType(const gunichar2 *root_path_name)
-{
- gchar *utf8_root_path_name;
- guint32 drive_type;
-
- if (root_path_name == NULL) {
- utf8_root_path_name = g_strdup (g_get_current_dir());
- if (utf8_root_path_name == NULL) {
- return(DRIVE_NO_ROOT_DIR);
- }
- }
- else {
- utf8_root_path_name = mono_unicode_to_external (root_path_name);
- if (utf8_root_path_name == NULL) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
- return(DRIVE_NO_ROOT_DIR);
- }
-
- /* strip trailing slash for compare below */
- if (g_str_has_suffix(utf8_root_path_name, "/") && utf8_root_path_name [1] != 0) {
- utf8_root_path_name[strlen(utf8_root_path_name) - 1] = 0;
- }
- }
- drive_type = GetDriveTypeFromPath (utf8_root_path_name);
- g_free (utf8_root_path_name);
-
- return (drive_type);
-}
-
-#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__)
-static gchar*
-get_fstypename (gchar *utfpath)
-{
-#if defined (PLATFORM_MACOSX) || defined (__linux__)
- struct statfs stat;
-#if __linux__
- _wapi_drive_type *current;
-#endif
- if (statfs (utfpath, &stat) == -1)
- return NULL;
-#if PLATFORM_MACOSX
- return g_strdup (stat.f_fstypename);
-#else
- current = &_wapi_drive_types[0];
- while (current->drive_type != DRIVE_UNKNOWN) {
- if (stat.f_type == current->fstypeid)
- return g_strdup (current->fstype);
- current++;
- }
- return NULL;
-#endif
-#else
- return NULL;
-#endif
-}
-
-/* Linux has struct statfs which has a different layout */
-gboolean
-GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize)
-{
- gchar *utfpath;
- gchar *fstypename;
- gboolean status = FALSE;
- glong len;
-
- // We only support getting the file system type
- if (fsbuffer == NULL)
- return 0;
-
- utfpath = mono_unicode_to_external (path);
- if ((fstypename = get_fstypename (utfpath)) != NULL){
- gunichar2 *ret = g_utf8_to_utf16 (fstypename, -1, NULL, &len, NULL);
- if (ret != NULL && len < fsbuffersize){
- memcpy (fsbuffer, ret, len * sizeof (gunichar2));
- fsbuffer [len] = 0;
- status = TRUE;
- }
- if (ret != NULL)
- g_free (ret);
- g_free (fstypename);
- }
- g_free (utfpath);
- return status;
-}
-#endif
-
-void
-_wapi_io_init (void)
-{
- mono_os_mutex_init (&stdhandle_mutex);
- mono_os_mutex_init (&file_share_mutex);
-
- mono_w32handle_register_ops (MONO_W32HANDLE_FILE, &_wapi_file_ops);
- mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
- mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops);
- mono_w32handle_register_ops (MONO_W32HANDLE_PIPE, &_wapi_pipe_ops);
-
-/* mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
-/* MONO_W32HANDLE_CAP_WAIT); */
-/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
-/* MONO_W32HANDLE_CAP_WAIT); */
-
- if (g_getenv ("MONO_STRICT_IO_EMULATION"))
- lock_while_writing = TRUE;
-}
-
-void
-_wapi_io_cleanup (void)
-{
- mono_os_mutex_destroy (&file_share_mutex);
-
- if (file_share_hash)
- g_hash_table_destroy (file_share_hash);
-}
+++ /dev/null
-/*
- * io.h: File, console and find handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_IO_H_
-#define _WAPI_IO_H_
-
-#include <stdlib.h>
-
-#include "mono/io-layer/wapi.h"
-
-G_BEGIN_DECLS
-
-typedef struct _WapiSecurityAttributes WapiSecurityAttributes;
-
-struct _WapiSecurityAttributes
-{
- guint32 nLength;
- gpointer lpSecurityDescriptor;
- gboolean bInheritHandle;
-};
-
-typedef struct _WapiOverlapped WapiOverlapped;
-
-struct _WapiOverlapped
-{
- guint32 Internal;
- guint32 InternalHigh;
- guint32 Offset;
- guint32 OffsetHigh;
- gpointer hEvent;
- gpointer handle1;
- gpointer handle2;
-};
-
-typedef void (*WapiOverlappedCB) (guint32 error, guint32 numbytes,
- WapiOverlapped *overlapped);
-
-#define GENERIC_READ 0x80000000
-#define GENERIC_WRITE 0x40000000
-#define GENERIC_EXECUTE 0x20000000
-#define GENERIC_ALL 0x10000000
-
-#define FILE_SHARE_READ 0x00000001
-#define FILE_SHARE_WRITE 0x00000002
-#define FILE_SHARE_DELETE 0x00000004
-
-#define CREATE_NEW 1
-#define CREATE_ALWAYS 2
-#define OPEN_EXISTING 3
-#define OPEN_ALWAYS 4
-#define TRUNCATE_EXISTING 5
-
-
-#define FILE_ATTRIBUTE_READONLY 0x00000001
-#define FILE_ATTRIBUTE_HIDDEN 0x00000002
-#define FILE_ATTRIBUTE_SYSTEM 0x00000004
-#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
-#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
-#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
-#define FILE_ATTRIBUTE_NORMAL 0x00000080
-#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
-#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
-#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
-#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
-#define FILE_ATTRIBUTE_OFFLINE 0x00001000
-#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
-#define FILE_FLAG_OPEN_NO_RECALL 0x00100000
-#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
-#define FILE_FLAG_POSIX_SEMANTICS 0x01000000
-#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
-#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
-#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
-#define FILE_FLAG_RANDOM_ACCESS 0x10000000
-#define FILE_FLAG_NO_BUFFERING 0x20000000
-#define FILE_FLAG_OVERLAPPED 0x40000000
-#define FILE_FLAG_WRITE_THROUGH 0x80000000
-
-#define REPLACEFILE_WRITE_THROUGH 0x00000001
-#define REPLACEFILE_IGNORE_MERGE_ERRORS 0x00000002
-
-#define MAX_PATH 260
-
-typedef enum {
- STD_INPUT_HANDLE=-10,
- STD_OUTPUT_HANDLE=-11,
- STD_ERROR_HANDLE=-12
-} WapiStdHandle;
-
-typedef enum {
- FILE_BEGIN=0,
- FILE_CURRENT=1,
- FILE_END=2
-} WapiSeekMethod;
-
-typedef enum {
- FILE_TYPE_UNKNOWN=0x0000,
- FILE_TYPE_DISK=0x0001,
- FILE_TYPE_CHAR=0x0002,
- FILE_TYPE_PIPE=0x0003,
- FILE_TYPE_REMOTE=0x8000
-} WapiFileType;
-
-typedef enum {
- DRIVE_UNKNOWN=0,
- DRIVE_NO_ROOT_DIR=1,
- DRIVE_REMOVABLE=2,
- DRIVE_FIXED=3,
- DRIVE_REMOTE=4,
- DRIVE_CDROM=5,
- DRIVE_RAMDISK=6
-} WapiDriveType;
-
-typedef enum {
- GetFileExInfoStandard=0x0000,
- GetFileExMaxInfoLevel=0x0001
-} WapiGetFileExInfoLevels;
-
-typedef struct
-{
- guint16 wYear;
- guint16 wMonth;
- guint16 wDayOfWeek;
- guint16 wDay;
- guint16 wHour;
- guint16 wMinute;
- guint16 wSecond;
- guint16 wMilliseconds;
-} WapiSystemTime;
-
-typedef struct {
-#if G_BYTE_ORDER == G_BIG_ENDIAN
- guint32 dwHighDateTime;
- guint32 dwLowDateTime;
-#else
- guint32 dwLowDateTime;
- guint32 dwHighDateTime;
-#endif
-} WapiFileTime;
-
-typedef struct
-{
- guint32 dwFileAttributes;
- WapiFileTime ftCreationTime;
- WapiFileTime ftLastAccessTime;
- WapiFileTime ftLastWriteTime;
- guint32 nFileSizeHigh;
- guint32 nFileSizeLow;
- guint32 dwReserved0;
- guint32 dwReserved1;
- gunichar2 cFileName [MAX_PATH];
- gunichar2 cAlternateFileName [14];
-} WapiFindData;
-
-typedef struct
-{
- guint32 dwFileAttributes;
- WapiFileTime ftCreationTime;
- WapiFileTime ftLastAccessTime;
- WapiFileTime ftLastWriteTime;
- guint32 nFileSizeHigh;
- guint32 nFileSizeLow;
-} WapiFileAttributesData;
-
-typedef union {
- struct {
- guint32 LowPart;
- guint32 HighPart;
- } u;
- guint64 QuadPart;
-} ULARGE_INTEGER;
-
-#define INVALID_SET_FILE_POINTER ((guint32)-1)
-#define INVALID_FILE_SIZE ((guint32)0xFFFFFFFF)
-#define INVALID_FILE_ATTRIBUTES ((guint32)-1)
-
-extern gpointer CreateFile(const gunichar2 *name, guint32 fileaccess,
- guint32 sharemode,
- WapiSecurityAttributes *security,
- guint32 createmode,
- guint32 attrs, gpointer tmplate);
-extern gboolean DeleteFile(const gunichar2 *name);
-extern gpointer GetStdHandle(WapiStdHandle stdhandle);
-extern gboolean ReadFile(gpointer handle, gpointer buffer, guint32 numbytes,
- guint32 *bytesread, WapiOverlapped *overlapped);
-extern gboolean WriteFile(gpointer handle, gconstpointer buffer,
- guint32 numbytes, guint32 *byteswritten,
- WapiOverlapped *overlapped);
-extern gboolean FlushFileBuffers(gpointer handle);
-extern gboolean SetEndOfFile(gpointer handle);
-extern guint32 SetFilePointer(gpointer handle, gint32 movedistance,
- gint32 *highmovedistance, guint32 method);
-extern WapiFileType GetFileType(gpointer handle);
-extern guint32 GetFileSize(gpointer handle, guint32 *highsize);
-extern gboolean GetFileTime(gpointer handle, WapiFileTime *create_time,
- WapiFileTime *last_access,
- WapiFileTime *last_write);
-extern gboolean SetFileTime(gpointer handle, const WapiFileTime *create_time,
- const WapiFileTime *last_access,
- const WapiFileTime *last_write);
-extern gboolean FileTimeToSystemTime(const WapiFileTime *file_time,
- WapiSystemTime *system_time);
-extern gpointer FindFirstFile (const gunichar2 *pattern,
- WapiFindData *find_data);
-extern gboolean FindNextFile (gpointer handle, WapiFindData *find_data);
-extern gboolean FindClose (gpointer handle);
-extern gboolean CreateDirectory (const gunichar2 *name,
- WapiSecurityAttributes *security);
-extern gboolean RemoveDirectory (const gunichar2 *name);
-extern gboolean MoveFile (const gunichar2 *name, const gunichar2 *dest_name);
-extern gboolean CopyFile (const gunichar2 *name, const gunichar2 *dest_name,
- gboolean fail_if_exists);
-extern gboolean ReplaceFile (const gunichar2 *replacedFileName, const gunichar2 *replacementFileName,
- const gunichar2 *backupFileName, guint32 replaceFlags,
- gpointer exclude, gpointer reserved);
-extern guint32 GetFileAttributes (const gunichar2 *name);
-extern gboolean GetFileAttributesEx (const gunichar2 *name,
- WapiGetFileExInfoLevels level,
- gpointer info);
-extern gboolean SetFileAttributes (const gunichar2 *name, guint32 attrs);
-extern guint32 GetCurrentDirectory (guint32 length, gunichar2 *buffer);
-extern gboolean SetCurrentDirectory (const gunichar2 *path);
-extern gboolean CreatePipe (gpointer *readpipe, gpointer *writepipe,
- WapiSecurityAttributes *security, guint32 size);
-extern gint32 GetLogicalDriveStrings (guint32 len, gunichar2 *buf);
-extern gboolean GetDiskFreeSpaceEx(const gunichar2 *path_name, ULARGE_INTEGER *free_bytes_avail,
- ULARGE_INTEGER *total_number_of_bytes,
- ULARGE_INTEGER *total_number_of_free_bytes);
-extern guint32 GetDriveType(const gunichar2 *root_path_name);
-extern gboolean LockFile (gpointer handle, guint32 offset_low,
- guint32 offset_high, guint32 length_low,
- guint32 length_high);
-extern gboolean UnlockFile (gpointer handle, guint32 offset_low,
- guint32 offset_high, guint32 length_low,
- guint32 length_high);
-extern gboolean GetVolumeInformation (const gunichar2 *path, gunichar2 *volumename, int volumesize, int *outserial, int *maxcomp, int *fsflags, gunichar2 *fsbuffer, int fsbuffersize);
-
-
-extern void _wapi_io_init (void);
-extern void _wapi_io_cleanup (void);
-
-G_END_DECLS
-
-#endif /* _WAPI_IO_H_ */
+++ /dev/null
-/*
- * io.c: File, console and find handles
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright (c) 2002-2009 Novell, Inc.
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#include <config.h>
-#include <stdio.h>
-#include <glib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-gboolean
-_wapi_lock_file_region (int fd, off_t offset, off_t length)
-{
-#if defined(__native_client__)
- printf("WARNING: locking.c: _wapi_lock_file_region(): fcntl() not available on Native Client!\n");
- // behave as below -- locks are not available
- return(TRUE);
-#else
- struct flock lock_data;
- int ret;
-
- if (offset < 0 || length < 0) {
- SetLastError (ERROR_INVALID_PARAMETER);
- return(FALSE);
- }
-
- lock_data.l_type = F_WRLCK;
- lock_data.l_whence = SEEK_SET;
- lock_data.l_start = offset;
- lock_data.l_len = length;
-
- do {
- ret = fcntl (fd, F_SETLK, &lock_data);
- } while(ret == -1 && errno == EINTR);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
-
- if (ret == -1) {
- /*
- * if locks are not available (NFS for example),
- * ignore the error
- */
- if (errno == ENOLCK
-#ifdef EOPNOTSUPP
- || errno == EOPNOTSUPP
-#endif
-#ifdef ENOTSUP
- || errno == ENOTSUP
-#endif
- ) {
- return (TRUE);
- }
-
- SetLastError (ERROR_LOCK_VIOLATION);
- return(FALSE);
- }
-
- return(TRUE);
-#endif /* __native_client__ */
-}
-
-gboolean
-_wapi_unlock_file_region (int fd, off_t offset, off_t length)
-{
-#if defined(__native_client__)
- printf("WARNING: locking.c: _wapi_unlock_file_region(): fcntl() not available on Native Client!\n");
- return (TRUE);
-#else
- struct flock lock_data;
- int ret;
-
- lock_data.l_type = F_UNLCK;
- lock_data.l_whence = SEEK_SET;
- lock_data.l_start = offset;
- lock_data.l_len = length;
-
- do {
- ret = fcntl (fd, F_SETLK, &lock_data);
- } while(ret == -1 && errno == EINTR);
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
-
- if (ret == -1) {
- /*
- * if locks are not available (NFS for example),
- * ignore the error
- */
- if (errno == ENOLCK
-#ifdef EOPNOTSUPP
- || errno == EOPNOTSUPP
-#endif
-#ifdef ENOTSUP
- || errno == ENOTSUP
-#endif
- ) {
- return (TRUE);
- }
-
- SetLastError (ERROR_LOCK_VIOLATION);
- return(FALSE);
- }
-
- return(TRUE);
-#endif /* __native_client__ */
-}
-
-gboolean
-LockFile (gpointer handle, guint32 offset_low, guint32 offset_high,
- guint32 length_low, guint32 length_high)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- off_t offset, length;
- int fd = GPOINTER_TO_UINT(handle);
-
- ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if (ok == FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (!(file_handle->fileaccess & GENERIC_READ) &&
- !(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
- offset = ((gint64)offset_high << 32) | offset_low;
- length = ((gint64)length_high << 32) | length_low;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
-#else
- if (offset_high > 0 || length_high > 0) {
- SetLastError (ERROR_INVALID_PARAMETER);
- return (FALSE);
- }
- offset = offset_low;
- length = length_low;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %ld, length %ld", __func__,
- handle, offset, length);
-#endif
-
- return(_wapi_lock_file_region (fd, offset, length));
-}
-
-gboolean
-UnlockFile (gpointer handle, guint32 offset_low,
- guint32 offset_high, guint32 length_low,
- guint32 length_high)
-{
- struct _WapiHandle_file *file_handle;
- gboolean ok;
- off_t offset, length;
- int fd = GPOINTER_TO_UINT(handle);
-
- ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
- (gpointer *)&file_handle);
- if (ok == FALSE) {
- g_warning ("%s: error looking up file handle %p", __func__,
- handle);
- SetLastError (ERROR_INVALID_HANDLE);
- return(FALSE);
- }
-
- if (!(file_handle->fileaccess & GENERIC_READ) &&
- !(file_handle->fileaccess & GENERIC_WRITE) &&
- !(file_handle->fileaccess & GENERIC_ALL)) {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
- SetLastError (ERROR_ACCESS_DENIED);
- return(FALSE);
- }
-
-#ifdef HAVE_LARGE_FILE_SUPPORT
- offset = ((gint64)offset_high << 32) | offset_low;
- length = ((gint64)length_high << 32) | length_low;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
-#else
- offset = offset_low;
- length = length_low;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
-#endif
-
- return(_wapi_unlock_file_region (fd, offset, length));
-}
+++ /dev/null
-/*
- * posix.c: Posix-specific support.
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- * Copyright (c) 2002-2009 Novell, Inc.
- * Copyright 2011 Xamarin Inc
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-#include <glib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdio.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/wapi-private.h>
-#include <mono/io-layer/io-private.h>
-#include <mono/io-layer/io-trace.h>
-#include <mono/utils/mono-logger-internals.h>
-#include <mono/metadata/w32handle.h>
-
-static guint32
-convert_from_flags(int flags)
-{
- guint32 fileaccess=0;
-
-#ifndef O_ACCMODE
-#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
-#endif
-
- if((flags & O_ACCMODE) == O_RDONLY) {
- fileaccess=GENERIC_READ;
- } else if ((flags & O_ACCMODE) == O_WRONLY) {
- fileaccess=GENERIC_WRITE;
- } else if ((flags & O_ACCMODE) == O_RDWR) {
- fileaccess=GENERIC_READ|GENERIC_WRITE;
- } else {
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags);
- }
-
- /* Maybe sort out create mode too */
-
- return(fileaccess);
-}
-
-
-gpointer _wapi_stdhandle_create (int fd, const gchar *name)
-{
- struct _WapiHandle_file file_handle = {0};
- gpointer handle;
- int flags;
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__,
- name, fd);
-
-#if !defined(__native_client__)
- /* Check if fd is valid */
- do {
- flags=fcntl(fd, F_GETFL);
- } while (flags == -1 && errno == EINTR);
-
- if(flags==-1) {
- /* Invalid fd. Not really much point checking for EBADF
- * specifically
- */
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd,
- strerror(errno));
-
- SetLastError (_wapi_get_win32_file_error (errno));
- return(INVALID_HANDLE_VALUE);
- }
- file_handle.fileaccess=convert_from_flags(flags);
-#else
- /*
- * fcntl will return -1 in nacl, as there is no real file system API.
- * Yet, standard streams are available.
- */
- file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
-#endif
-
- file_handle.fd = fd;
- file_handle.filename = g_strdup(name);
- /* some default security attributes might be needed */
- file_handle.security_attributes=0;
-
- /* Apparently input handles can't be written to. (I don't
- * know if output or error handles can't be read from.)
- */
- if (fd == 0) {
- file_handle.fileaccess &= ~GENERIC_WRITE;
- }
-
- file_handle.sharemode=0;
- file_handle.attrs=0;
-
- handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
- if (handle == INVALID_HANDLE_VALUE) {
- g_warning ("%s: error creating file handle", __func__);
- SetLastError (ERROR_GEN_FAILURE);
- return(INVALID_HANDLE_VALUE);
- }
-
- MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
-
- return(handle);
-}
-
+++ /dev/null
-/*
- * uglify.h: Optional header to provide the nasty w32 typedefs
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_UGLIFY_H_
-#define _WAPI_UGLIFY_H_
-
-/* Include this file if you insist on using the nasty Win32 typedefs */
-
-#include <stdlib.h>
-
-#include "mono/io-layer/wapi.h"
-
-typedef const gunichar2 *LPCTSTR;
-typedef gunichar2 *LPTSTR;
-typedef const char *LPCSTR;
-typedef char *LPSTR;
-typedef guint8 BYTE;
-typedef guint8 *LPBYTE;
-typedef guint16 WORD;
-typedef guint32 DWORD;
-typedef gpointer PVOID;
-typedef gpointer LPVOID;
-typedef gboolean BOOL;
-typedef guint32 *LPDWORD;
-typedef gint32 LONG;
-typedef guint32 ULONG;
-typedef gint32 *PLONG;
-typedef guint64 LONGLONG;
-typedef gunichar2 TCHAR;
-typedef size_t SIZE_T;
-typedef guint64 ULONG64;
-typedef guint UINT;
-typedef gconstpointer LPCVOID;
-
-typedef gpointer HANDLE;
-typedef gpointer *LPHANDLE;
-typedef gpointer HMODULE;
-typedef gpointer HINSTANCE;
-typedef gpointer HWND;
-typedef gpointer HKEY;
-
-typedef WapiSecurityAttributes SECURITY_ATTRIBUTES;
-typedef WapiSecurityAttributes *LPSECURITY_ATTRIBUTES;
-typedef WapiOverlapped *LPOVERLAPPED;
-typedef WapiOverlappedCB LPOVERLAPPED_COMPLETION_ROUTINE;
-typedef WapiFileTime FILETIME;
-typedef WapiFileTime *LPFILETIME;
-typedef WapiSystemTime SYSTEMTIME;
-typedef WapiSystemTime *LPSYSTEMTIME;
-typedef WapiFindData WIN32_FIND_DATA;
-typedef WapiFindData *LPWIN32_FIND_DATA;
-typedef WapiFileAttributesData WIN32_FILE_ATTRIBUTE_DATA;
-typedef WapiGetFileExInfoLevels GET_FILEEX_INFO_LEVELS;
-
-#define CONST const
-#define VOID void
-
-#define IN
-#define OUT
-#define WINAPI
-
-#endif /* _WAPI_UGLIFY_H_ */
+++ /dev/null
-/*
- * wapi-private.h: internal definitions of handles and shared memory layout
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002-2006 Novell, Inc.
- */
-
-#ifndef _WAPI_PRIVATE_H_
-#define _WAPI_PRIVATE_H_
-
-#include <config.h>
-#include <glib.h>
-#include <sys/stat.h>
-
-#include <mono/io-layer/wapi.h>
-#include <mono/io-layer/io.h>
-
-#include <mono/utils/mono-os-mutex.h>
-
-/* There doesn't seem to be a defined symbol for this */
-#define _WAPI_THREAD_CURRENT (gpointer)0xFFFFFFFE
-
-extern gboolean _wapi_has_shut_down;
-
-#include <mono/io-layer/io-private.h>
-#include <mono/metadata/w32handle.h>
-
-struct _WapiHandle_shared_ref
-{
- /* This will be split 16:16 with the shared file segment in
- * the top half, when I implement space increases
- */
- guint32 offset;
-};
-
-struct _WapiFileShare
-{
-#ifdef WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA
- WAPI_FILE_SHARE_PLATFORM_EXTRA_DATA
-#endif
- guint64 device;
- guint64 inode;
- pid_t opened_by_pid;
- guint32 sharemode;
- guint32 access;
- guint32 handle_refs;
- guint32 timestamp;
-};
-
-typedef struct _WapiFileShare _WapiFileShare;
-
-#endif /* _WAPI_PRIVATE_H_ */
+++ /dev/null
-/*
- * wapi-remap.h: io-layer symbol remapping support
- *
- * (C) 2014 Xamarin, Inc.
- */
-
-#ifndef __WAPI_REMAP_H__
-#define __WAPI_REMAP_H__
-
-/*
- * The windows function names used by the io-layer can collide with symbols in system and 3rd party libs, esp. on osx/ios. So remap them to
- * wapi_<funcname>.
- */
-
-#define GetLastError wapi_GetLastError
-#define SetLastError wapi_SetLastError
-#define CloseHandle wapi_CloseHandle
-#define CreateFile wapi_CreateFile
-#define DeleteFile wapi_DeleteFile
-#define GetStdHandle wapi_GetStdHandle
-#define ReadFile wapi_ReadFile
-#define WriteFile wapi_WriteFile
-#define FlushFileBuffers wapi_FlushFileBuffers
-#define SetEndOfFile wapi_SetEndOfFile
-#define SetFilePointer wapi_SetFilePointer
-#define GetFileType wapi_GetFileType
-#define GetFileSize wapi_GetFileSize
-#define GetFileTime wapi_GetFileTime
-#define SetFileTime wapi_SetFileTime
-#define FileTimeToSystemTime wapi_FileTimeToSystemTime
-#define FindFirstFile wapi_FindFirstFile
-#define FindNextFile wapi_FindNextFile
-#define FindClose wapi_FindClose
-#define CreateDirectory wapi_CreateDirectory
-#define RemoveDirectory wapi_RemoveDirectory
-#define MoveFile wapi_MoveFile
-#define CopyFile wapi_CopyFile
-#define ReplaceFile wapi_ReplaceFile
-#define GetFileAttributes wapi_GetFileAttributes
-#define GetFileAttributesEx wapi_GetFileAttributesEx
-#define SetFileAttributes wapi_SetFileAttributes
-#define GetCurrentDirectory wapi_GetCurrentDirectory
-#define SetCurrentDirectory wapi_SetCurrentDirectory
-#define CreatePipe wapi_CreatePipe
-#define GetLogicalDriveStrings wapi_GetLogicalDriveStrings
-#define GetDiskFreeSpaceEx wapi_GetDiskFreeSpaceEx
-#define GetDriveType wapi_GetDriveType
-#define LockFile wapi_LockFile
-#define UnlockFile wapi_UnlockFile
-#define GetVolumeInformation wapi_GetVolumeInformation
-#define ImpersonateLoggedOnUser wapi_ImpersonateLoggedOnUser
-#define RevertToSelf wapi_RevertToSelf
-#define GetSystemInfo wapi_GetSystemInfo
-
-#endif /* __WAPI_REMAP_H__ */
+++ /dev/null
-
-#include "wapi.h"
-
-#include "io-trace.h"
-#include "io.h"
-
-#include "mono/utils/mono-lazy-init.h"
-#include "mono/metadata/w32handle.h"
-
-gboolean _wapi_has_shut_down = FALSE;
-
-void
-wapi_init (void)
-{
- _wapi_io_init ();
-}
-
-void
-wapi_cleanup (void)
-{
- g_assert (_wapi_has_shut_down == FALSE);
- _wapi_has_shut_down = TRUE;
-
- _wapi_error_cleanup ();
- _wapi_io_cleanup ();
-}
-
-/* Use this instead of getpid(), to cope with linuxthreads. It's a
- * function rather than a variable lookup because we need to get at
- * this before share_init() might have been called. */
-static mono_lazy_init_t _wapi_pid_init_lazy = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
-static pid_t _wapi_pid;
-
-static void
-_wapi_pid_init (void)
-{
- _wapi_pid = getpid ();
-}
-
-pid_t
-wapi_getpid (void)
-{
- mono_lazy_initialize (&_wapi_pid_init_lazy, _wapi_pid_init);
- return _wapi_pid;
-}
-
-/**
- * CloseHandle:
- * @handle: The handle to release
- *
- * Closes and invalidates @handle, releasing any resources it
- * consumes. When the last handle to a temporary or non-persistent
- * object is closed, that object can be deleted. Closing the same
- * handle twice is an error.
- *
- * Return value: %TRUE on success, %FALSE otherwise.
- */
-gboolean CloseHandle(gpointer handle)
-{
- if (handle == INVALID_HANDLE_VALUE){
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
- if (handle == (gpointer)0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
- /* Problem: because we map file descriptors to the
- * same-numbered handle we can't tell the difference
- * between a bogus handle and the handle to stdin.
- * Assume that it's the console handle if that handle
- * exists...
- */
- SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- mono_w32handle_unref (handle);
- return TRUE;
-}
+++ /dev/null
-/*
- * wapi.h: Public include files
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- *
- * (C) 2002 Ximian, Inc.
- */
-
-#ifndef _WAPI_WAPI_H_
-#define _WAPI_WAPI_H_
-
-#include <glib.h>
-
-#include <sys/types.h>
-
-#include <mono/io-layer/wapi-remap.h>
-#include <mono/io-layer/io.h>
-#include <mono/io-layer/io-portability.h>
-#include <mono/io-layer/error.h>
-
-G_BEGIN_DECLS
-
-#define WAIT_FAILED ((int) 0xFFFFFFFF)
-#define WAIT_OBJECT_0 ((int) 0x00000000)
-#define WAIT_ABANDONED_0 ((int) 0x00000080)
-#define WAIT_TIMEOUT ((int) 0x00000102)
-#define WAIT_IO_COMPLETION ((int) 0x000000C0)
-
-void
-wapi_init (void);
-
-void
-wapi_cleanup (void);
-
-gboolean
-CloseHandle (gpointer handle);
-
-pid_t
-wapi_getpid (void);
-
-G_END_DECLS
-
-#endif /* _WAPI_WAPI_H_ */
+++ /dev/null
-/* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * _wapi_glob(3) -- a subset of the one defined in POSIX 1003.2.
- *
- * Optional extra services, controlled by flags not defined by POSIX:
- *
- * GLOB_MAGCHAR:
- * Set in gl_flags if pattern contained a globbing character.
- */
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <glib.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "wapi_glob.h"
-
-#define EOS '\0'
-#define NOT '!'
-#define QUESTION '?'
-#define QUOTE '\\'
-#define STAR '*'
-
-#ifndef DEBUG
-
-#define M_QUOTE 0x8000
-#define M_PROTECT 0x4000
-#define M_MASK 0xffff
-#define M_ASCII 0x00ff
-
-typedef unsigned short Char;
-
-#else
-
-#define M_QUOTE 0x80
-#define M_PROTECT 0x40
-#define M_MASK 0xff
-#define M_ASCII 0x7f
-
-typedef char Char;
-
-#endif
-
-
-#define CHAR(c) ((gchar)((c)&M_ASCII))
-#define META(c) ((gchar)((c)|M_QUOTE))
-#define M_ALL META('*')
-#define M_ONE META('?')
-#define ismeta(c) (((c)&M_QUOTE) != 0)
-
-
-static int g_Ctoc(const gchar *, char *, unsigned int);
-static int glob0(GDir *dir, const gchar *, wapi_glob_t *, gboolean,
- gboolean);
-static int glob1(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *,
- gboolean, gboolean);
-static int glob3(GDir *dir, gchar *, gchar *, wapi_glob_t *, size_t *,
- gboolean, gboolean);
-static int globextend(const gchar *, wapi_glob_t *, size_t *);
-static int match(const gchar *, gchar *, gchar *, gboolean);
-#ifdef DEBUG_ENABLED
-static void qprintf(const char *, Char *);
-#endif
-
-int
-_wapi_glob(GDir *dir, const char *pattern, int flags, wapi_glob_t *pglob)
-{
- const unsigned char *patnext;
- int c;
- gchar *bufnext, *bufend, patbuf[PATH_MAX];
-
- patnext = (unsigned char *) pattern;
- if (!(flags & WAPI_GLOB_APPEND)) {
- pglob->gl_pathc = 0;
- pglob->gl_pathv = NULL;
- pglob->gl_offs = 0;
- }
- pglob->gl_flags = flags & ~WAPI_GLOB_MAGCHAR;
-
- bufnext = patbuf;
- bufend = bufnext + PATH_MAX - 1;
-
- /* Protect the quoted characters. */
- while (bufnext < bufend && (c = *patnext++) != EOS)
- if (c == QUOTE) {
- if ((c = *patnext++) == EOS) {
- c = QUOTE;
- --patnext;
- }
- *bufnext++ = c | M_PROTECT;
- } else
- *bufnext++ = c;
-
- *bufnext = EOS;
-
- return glob0(dir, patbuf, pglob, flags & WAPI_GLOB_IGNORECASE,
- flags & WAPI_GLOB_UNIQUE);
-}
-
-/*
- * The main glob() routine: compiles the pattern (optionally processing
- * quotes), calls glob1() to do the real pattern matching, and finally
- * sorts the list (unless unsorted operation is requested). Returns 0
- * if things went well, nonzero if errors occurred. It is not an error
- * to find no matches.
- */
-static int
-glob0(GDir *dir, const gchar *pattern, wapi_glob_t *pglob, gboolean ignorecase,
- gboolean unique)
-{
- const gchar *qpatnext;
- int c, err, oldpathc;
- gchar *bufnext, patbuf[PATH_MAX];
- size_t limit = 0;
-
- qpatnext = pattern;
- oldpathc = pglob->gl_pathc;
- bufnext = patbuf;
-
- /* We don't need to check for buffer overflow any more. */
- while ((c = *qpatnext++) != EOS) {
- switch (c) {
- case QUESTION:
- pglob->gl_flags |= WAPI_GLOB_MAGCHAR;
- *bufnext++ = M_ONE;
- break;
- case STAR:
- pglob->gl_flags |= WAPI_GLOB_MAGCHAR;
- /* collapse adjacent stars to one,
- * to avoid exponential behavior
- */
- if (bufnext == patbuf || bufnext[-1] != M_ALL)
- *bufnext++ = M_ALL;
- break;
- default:
- *bufnext++ = CHAR(c);
- break;
- }
- }
- *bufnext = EOS;
-#ifdef DEBUG_ENABLED
- qprintf("glob0:", patbuf);
-#endif
-
- if ((err = glob1(dir, patbuf, patbuf+PATH_MAX-1, pglob, &limit,
- ignorecase, unique)) != 0)
- return(err);
-
- if (pglob->gl_pathc == oldpathc) {
- return(WAPI_GLOB_NOMATCH);
- }
-
- return(0);
-}
-
-static int
-glob1(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
- size_t *limitp, gboolean ignorecase, gboolean unique)
-{
- /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
- if (*pattern == EOS)
- return(0);
- return(glob3(dir, pattern, pattern_last, pglob, limitp, ignorecase,
- unique));
-}
-
-static gboolean contains (wapi_glob_t *pglob, const gchar *name)
-{
- int i;
- char **pp;
-
- if (pglob->gl_pathv != NULL) {
- pp = pglob->gl_pathv + pglob->gl_offs;
- for (i = pglob->gl_pathc; i--; ++pp) {
- if (*pp) {
- if (!strcmp (*pp, name)) {
- return(TRUE);
- }
- }
- }
- }
-
- return(FALSE);
-}
-
-static int
-glob3(GDir *dir, gchar *pattern, gchar *pattern_last, wapi_glob_t *pglob,
- size_t *limitp, gboolean ignorecase, gboolean unique)
-{
- const gchar *name;
-
- /* Search directory for matching names. */
- while ((name = g_dir_read_name(dir))) {
- if (!match(name, pattern, pattern + strlen (pattern),
- ignorecase)) {
- continue;
- }
- if (!unique ||
- !contains (pglob, name)) {
- globextend (name, pglob, limitp);
- }
- }
-
- return(0);
-}
-
-
-/*
- * Extend the gl_pathv member of a wapi_glob_t structure to accommodate a new item,
- * add the new item, and update gl_pathc.
- *
- * This assumes the BSD realloc, which only copies the block when its size
- * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
- * behavior.
- *
- * Return 0 if new item added, error code if memory couldn't be allocated.
- *
- * Invariant of the wapi_glob_t structure:
- * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
- * gl_pathv points to (gl_offs + gl_pathc + 1) items.
- */
-static int
-globextend(const gchar *path, wapi_glob_t *pglob, size_t *limitp)
-{
- char **pathv;
- int i;
- unsigned int newsize, len;
- char *copy;
- const gchar *p;
-
- newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
- /* FIXME: Can just use realloc(). */
- pathv = (char **)(pglob->gl_pathv ? g_realloc ((char *)pglob->gl_pathv, newsize) :
- g_malloc (newsize));
- if (pathv == NULL) {
- if (pglob->gl_pathv) {
- g_free (pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
- return(WAPI_GLOB_NOSPACE);
- }
-
- if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
- /* first time around -- clear initial gl_offs items */
- pathv += pglob->gl_offs;
- for (i = pglob->gl_offs; --i >= 0; )
- *--pathv = NULL;
- }
- pglob->gl_pathv = pathv;
-
- for (p = path; *p++;)
- ;
- len = (size_t)(p - path);
- *limitp += len;
- if ((copy = (char *)malloc(len)) != NULL) {
- if (g_Ctoc(path, copy, len)) {
- g_free (copy);
- return(WAPI_GLOB_NOSPACE);
- }
- pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
- }
- pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
-
-#if 0
- /* Broken on opensuse 11 */
- if ((pglob->gl_flags & WAPI_GLOB_LIMIT) &&
- newsize + *limitp >= ARG_MAX) {
- errno = 0;
- return(WAPI_GLOB_NOSPACE);
- }
-#endif
-
- return(copy == NULL ? WAPI_GLOB_NOSPACE : 0);
-}
-
-
-/*
- * pattern matching function for filenames. Each occurrence of the *
- * pattern causes a recursion level.
- */
-static int
-match(const gchar *name, gchar *pat, gchar *patend, gboolean ignorecase)
-{
- gchar c;
-
- while (pat < patend) {
- c = *pat++;
- switch (c & M_MASK) {
- case M_ALL:
- if (pat == patend)
- return(1);
- do {
- if (match(name, pat, patend, ignorecase))
- return(1);
- } while (*name++ != EOS);
- return(0);
- case M_ONE:
- if (*name++ == EOS)
- return(0);
- break;
- default:
- if (ignorecase) {
- if (g_ascii_tolower (*name++) != g_ascii_tolower (c))
- return(0);
- } else {
- if (*name++ != c)
- return(0);
- }
-
- break;
- }
- }
- return(*name == EOS);
-}
-
-/* Free allocated data belonging to a wapi_glob_t structure. */
-void
-_wapi_globfree(wapi_glob_t *pglob)
-{
- int i;
- char **pp;
-
- if (pglob->gl_pathv != NULL) {
- pp = pglob->gl_pathv + pglob->gl_offs;
- for (i = pglob->gl_pathc; i--; ++pp)
- if (*pp)
- g_free (*pp);
- g_free (pglob->gl_pathv);
- pglob->gl_pathv = NULL;
- }
-}
-
-static int
-g_Ctoc(const gchar *str, char *buf, unsigned int len)
-{
-
- while (len--) {
- if ((*buf++ = *str++) == EOS)
- return (0);
- }
- return (1);
-}
-
-#ifdef DEBUG_ENABLED
-static void
-qprintf(const char *str, Char *s)
-{
- Char *p;
-
- (void)printf("%s:\n", str);
- for (p = s; *p; p++)
- (void)printf("%c", CHAR(*p));
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
- (void)printf("\n");
- for (p = s; *p; p++)
- (void)printf("%c", ismeta(*p) ? '_' : ' ');
- (void)printf("\n");
-}
-#endif
+++ /dev/null
-/* $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $ */
-/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */
-
-/*
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Guido van Rossum.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)glob.h 8.1 (Berkeley) 6/2/93
- */
-
-#ifndef _WAPI_GLOB_H_
-#define _WAPI_GLOB_H_
-
-#include <glib.h>
-
-struct stat;
-typedef struct {
- int gl_pathc; /* Count of total paths so far. */
- int gl_offs; /* Reserved at beginning of gl_pathv. */
- int gl_flags; /* Copy of flags parameter to glob. */
- char **gl_pathv; /* List of paths matching pattern. */
-} wapi_glob_t;
-
-#define WAPI_GLOB_APPEND 0x0001 /* Append to output from previous call. */
-#define WAPI_GLOB_UNIQUE 0x0040 /* When appending only add items that aren't already in the list */
-#define WAPI_GLOB_NOSPACE (-1) /* Malloc call failed. */
-#define WAPI_GLOB_ABORTED (-2) /* Unignored error. */
-#define WAPI_GLOB_NOMATCH (-3) /* No match and WAPI_GLOB_NOCHECK not set. */
-#define WAPI_GLOB_NOSYS (-4) /* Function not supported. */
-
-#define WAPI_GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
-#define WAPI_GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */
-#define WAPI_GLOB_IGNORECASE 0x4000 /* Ignore case when matching */
-#define WAPI_GLOB_ABEND WAPI_GLOB_ABORTED /* backward compatibility */
-
-G_BEGIN_DECLS
-int _wapi_glob(GDir *dir, const char *, int, wapi_glob_t *);
-void _wapi_globfree(wapi_glob_t *);
-G_END_DECLS
-
-#endif /* !_WAPI_GLOB_H_ */
console-win32.c \
console-win32-internals.h \
cominterop-win32-internals.h \
- file-io-windows.c \
- file-io-windows-internals.h \
+ w32file-win32.c \
+ w32file-win32-internals.h \
icall-windows.c \
icall-windows-internals.h \
marshal-windows.c \
w32event-win32.c \
w32process-win32.c \
w32process-win32-internals.h \
- w32socket-win32.c
+ w32socket-win32.c \
+ w32error-win32.c
platform_sources = $(win32_sources)
w32process-unix-bsd.c \
w32process-unix-haiku.c \
w32process-unix-default.c \
- w32socket-unix.c
+ w32socket-unix.c \
+ w32file-unix.c \
+ w32file-unix-glob.c \
+ w32file-unix-glob.h \
+ w32error-unix.c
platform_sources = $(unix_sources)
endif
exception.c \
exception.h \
exception-internals.h \
- file-io.c \
- file-io.h \
- file-io-internals.h \
+ w32file.c \
+ w32file.h \
+ w32file-internals.h \
filewatcher.c \
filewatcher.h \
gc-internals.h \
w32handle-namespace.h \
w32handle-namespace.c \
w32handle.h \
- w32handle.c
+ w32handle.c \
+ w32error.h
# These source files have compile time dependencies on GC code
gc_dependent_sources = \
#include <mono/metadata/mono-debug.h>
#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/attach.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
#include <mono/metadata/lock-tracer.h>
#include <mono/metadata/console-io.h>
#include <mono/metadata/threads-types.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-threads.h>
#include <mono/metadata/w32handle.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/metadata/w32error.h>
+#include <mono/utils/w32api.h>
#ifdef HOST_WIN32
#include <direct.h>
#endif
{
guint16 *orig, *dest;
gboolean copy_result;
+ gint32 copy_error;
strcpy (src + srclen - tail_len, extension);
strcpy (target + targetlen - tail_len, extension);
dest = g_utf8_to_utf16 (target, strlen (target), NULL, NULL, NULL);
- DeleteFile (dest);
+ mono_w32file_delete (dest);
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
- copy_result = CopyFile (orig, dest, FALSE);
-#else
- copy_result = SUCCEEDED (CopyFile2 (orig, dest, NULL));
-#endif
+ copy_result = mono_w32file_copy (orig, dest, TRUE, ©_error);
/* Fix for bug #556884 - make sure the files have the correct mode so that they can be
* overwritten when updated in their original locations. */
if (copy_result)
- copy_result = SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+ copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
g_free (orig);
g_free (dest);
if (!u16_ini) {
return FALSE;
}
- handle = (void **)CreateFile (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
- NULL, CREATE_NEW, FileAttributes_Normal, NULL);
+ handle = (void **)mono_w32file_create (u16_ini, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, CREATE_NEW, FileAttributes_Normal);
g_free (u16_ini);
if (handle == INVALID_HANDLE_VALUE) {
return FALSE;
}
full_path = mono_path_resolve_symlinks (filename);
- result = WriteFile (handle, full_path, strlen (full_path), &n, NULL);
+ result = mono_w32file_write (handle, full_path, strlen (full_path), &n);
g_free (full_path);
- CloseHandle (handle);
+ mono_w32file_close (handle);
return result;
}
char *dir_name = g_path_get_dirname (filename);
MonoDomain *domain = mono_domain_get ();
char *shadow_dir;
+ gint32 copy_error;
mono_error_init (oerror);
orig = g_utf8_to_utf16 (filename, strlen (filename), NULL, NULL, NULL);
dest = g_utf8_to_utf16 (shadow, strlen (shadow), NULL, NULL, NULL);
- DeleteFile (dest);
+ mono_w32file_delete (dest);
/* Fix for bug #17066 - make sure we can read the file. if not then don't error but rather
* let the assembly fail to load. This ensures you can do Type.GetType("NS.T, NonExistantAssembly)
* and not have it runtime error" */
- attrs = GetFileAttributes (orig);
+ attrs = mono_w32file_get_attributes (orig);
if (attrs == INVALID_FILE_ATTRIBUTES) {
g_free (shadow);
return (char *)filename;
}
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
- copy_result = CopyFile (orig, dest, FALSE);
-#else
- copy_result = SUCCEEDED (CopyFile2 (orig, dest, NULL));
-#endif
+ copy_result = mono_w32file_copy (orig, dest, TRUE, ©_error);
/* Fix for bug #556884 - make sure the files have the correct mode so that they can be
* overwritten when updated in their original locations. */
if (copy_result)
- copy_result = SetFileAttributes (dest, FILE_ATTRIBUTE_NORMAL);
+ copy_result = mono_w32file_set_attributes (dest, FILE_ATTRIBUTE_NORMAL);
g_free (dest);
g_free (orig);
g_free (shadow);
/* Fix for bug #17251 - if file not found try finding assembly by other means (it is not fatal error) */
- if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND)
+ if (mono_w32error_get_last() == ERROR_FILE_NOT_FOUND || mono_w32error_get_last() == ERROR_PATH_NOT_FOUND)
return NULL; /* file not found, shadow copy failed */
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy (CopyFile).");
+ mono_error_set_execution_engine (oerror, "Failed to create shadow copy (mono_w32file_copy).");
return NULL;
}
if (!copy_result) {
g_free (shadow);
- mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (CopyFile).");
+ mono_error_set_execution_engine (oerror, "Failed to create shadow copy of sibling data (mono_w32file_copy).");
return NULL;
}
#include <mono/metadata/reflection-internals.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/mono-debug.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/mono-uri.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/mono-config-dirs.h>
#include <mono/utils/mono-threads.h>
#include "attach.h"
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
/*
* This module enables other processes to attach to a running mono process and
prop->value = value;
mono_property_bag_add (&class->infrequent_data, prop);
}
+
+void
+mono_class_set_is_com_object (MonoClass *klass)
+{
+#ifndef DISABLE_COM
+ mono_loader_lock ();
+ klass->is_com_object = 1;
+ mono_loader_unlock ();
+#endif
+}
* to 1, because we know the instance size now. After that we
* initialise all static fields.
*/
- /* size_inited is accessed without locks, so it needs a memory barrier */
- /* All flag bits should be written while holding the loader lock */
+
+ /* ALL BITFIELDS SHOULD BE WRITTEN WHILE HOLDING THE LOADER LOCK */
guint size_inited : 1;
guint valuetype : 1; /* derives from System.ValueType */
guint enumtype : 1; /* derives from System.Enum */
#ifdef DISABLE_COM
#define mono_class_is_com_object(klass) (FALSE)
-#define mono_class_set_is_com_object(klass) do {} while (0)
#else
#define mono_class_is_com_object(klass) ((klass)->is_com_object)
-#define mono_class_set_is_com_object(klass) do { (klass)->is_com_object = 1; } while (0)
#endif
MonoGenericContext *generic_context);
MonoMethod*
-mono_class_get_cctor (MonoClass *klass);
+mono_class_get_cctor (MonoClass *klass) MONO_LLVM_INTERNAL;
MonoMethod*
mono_class_get_finalizer (MonoClass *klass);
int
mono_method_get_vtable_index (MonoMethod *method);
+MonoMethod*
+mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error);
+
MonoMethod*
mono_method_search_in_array_class (MonoClass *klass, const char *name, MonoMethodSignature *sig);
void
mono_class_set_declsec_flags (MonoClass *class, guint32 value);
+void
+mono_class_set_is_com_object (MonoClass *klass);
+
/*Now that everything has been defined, let's include the inline functions */
#include <mono/metadata/class-inlines.h>
init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
{
if (cached_info) {
+ mono_loader_lock ();
klass->instance_size = cached_info->instance_size;
klass->sizes.class_size = cached_info->class_size;
klass->packing_size = cached_info->packing_size;
klass->has_references = cached_info->has_references;
klass->has_static_refs = cached_info->has_static_refs;
klass->no_special_static_fields = cached_info->no_special_static_fields;
+ mono_loader_unlock ();
}
else {
if (!klass->size_inited)
}
}
- mono_image_lock (klass->image);
-
+ mono_loader_lock ();
if (!klass->has_finalize_inited) {
klass->has_finalize = has_finalize ? 1 : 0;
mono_memory_barrier ();
klass->has_finalize_inited = TRUE;
}
-
- mono_image_unlock (klass->image);
+ mono_loader_unlock ();
return klass->has_finalize;
}
mono_error_cleanup (&error);
}
}
+ mono_loader_lock ();
if (klass->parent)
mono_class_setup_parent (klass, klass->parent);
klass->cast_class = gtd->cast_class;
klass->element_class = gtd->element_class;
}
+ mono_loader_unlock ();
}
gboolean
if (klass->nested_classes_inited)
return;
- if (!klass->type_token)
+ if (!klass->type_token) {
+ mono_loader_lock ();
klass->nested_classes_inited = TRUE;
+ mono_loader_unlock ();
+ return;
+ }
i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
classes = NULL;
interfaces = NULL;
}
- mono_image_lock (klass->image);
-
+ mono_loader_lock ();
if (!klass->interfaces_inited) {
klass->interface_count = interface_count;
klass->interfaces = interfaces;
klass->interfaces_inited = TRUE;
}
-
- mono_image_unlock (klass->image);
+ mono_loader_unlock ();
}
static void
MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
int field_idx = field - klass->fields;
-
if (gtd) {
MonoClassField *gfield = >d->fields [field_idx];
return mono_field_get_flags (gfield);
/* Declare all shared lazy type lookup functions */
GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)
+
+/**
+ * mono_method_get_base_method:
+ * @method: a method
+ * @definition: if true, get the definition
+ * @error: set on failure
+ *
+ * Given a virtual method associated with a subclass, return the corresponding
+ * method from an ancestor. If @definition is FALSE, returns the method in the
+ * superclass of the given method. If @definition is TRUE, return the method
+ * in the ancestor class where it was first declared. The type arguments will
+ * be inflated in the ancestor classes. If the method is not associated with a
+ * class, or isn't virtual, returns the method itself. On failure returns NULL
+ * and sets @error.
+ */
+MonoMethod*
+mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
+{
+ MonoClass *klass, *parent;
+ MonoGenericContext *generic_inst = NULL;
+ MonoMethod *result = NULL;
+ int slot;
+
+ if (method->klass == NULL)
+ return method;
+
+ if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
+ MONO_CLASS_IS_INTERFACE (method->klass) ||
+ method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
+ return method;
+
+ slot = mono_method_get_vtable_slot (method);
+ if (slot == -1)
+ return method;
+
+ klass = method->klass;
+ if (mono_class_is_ginst (klass)) {
+ generic_inst = mono_class_get_context (klass);
+ klass = mono_class_get_generic_class (klass)->container_class;
+ }
+
+retry:
+ if (definition) {
+ /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
+ for (parent = klass->parent; parent != NULL; parent = parent->parent) {
+ /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
+ or klass is the generic container class and generic_inst is the instantiation.
+
+ when we go to the parent, if the parent is an open constructed type, we need to
+ replace the type parameters by the definitions from the generic_inst, and then take it
+ apart again into the klass and the generic_inst.
+
+ For cases like this:
+ class C<T> : B<T, int> {
+ public override void Foo () { ... }
+ }
+ class B<U,V> : A<HashMap<U,V>> {
+ public override void Foo () { ... }
+ }
+ class A<X> {
+ public virtual void Foo () { ... }
+ }
+
+ if at each iteration the parent isn't open, we can skip inflating it. if at some
+ iteration the parent isn't generic (after possible inflation), we set generic_inst to
+ NULL;
+ */
+ MonoGenericContext *parent_inst = NULL;
+ if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
+ parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
+ return_val_if_nok (error, NULL);
+ }
+ if (mono_class_is_ginst (parent)) {
+ parent_inst = mono_class_get_context (parent);
+ parent = mono_class_get_generic_class (parent)->container_class;
+ }
+
+ mono_class_setup_vtable (parent);
+ if (parent->vtable_size <= slot)
+ break;
+ klass = parent;
+ generic_inst = parent_inst;
+ }
+ } else {
+ klass = klass->parent;
+ if (!klass)
+ return method;
+ if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
+ klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
+ return_val_if_nok (error, NULL);
+
+ generic_inst = NULL;
+ }
+ if (mono_class_is_ginst (klass)) {
+ generic_inst = mono_class_get_context (klass);
+ klass = mono_class_get_generic_class (klass)->container_class;
+ }
+
+ }
+
+ if (generic_inst) {
+ klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
+ return_val_if_nok (error, NULL);
+ }
+
+ if (klass == method->klass)
+ return method;
+
+ /*This is possible if definition == FALSE.
+ * Do it here to be really sure we don't read invalid memory.
+ */
+ if (slot >= klass->vtable_size)
+ return method;
+
+ mono_class_setup_vtable (klass);
+
+ result = klass->vtable [slot];
+ if (result == NULL) {
+ /* It is an abstract method */
+ gboolean found = FALSE;
+ gpointer iter = NULL;
+ while ((result = mono_class_get_methods (klass, &iter))) {
+ if (result->slot == slot) {
+ found = TRUE;
+ break;
+ }
+ }
+ /* found might be FALSE if we looked in an abstract class
+ * that doesn't override an abstract method of its
+ * parent:
+ * abstract class Base {
+ * public abstract void Foo ();
+ * }
+ * abstract class Derived : Base { }
+ * class Child : Derived {
+ * public override void Foo () { }
+ * }
+ *
+ * if m was Child.Foo and we ask for the base method,
+ * then we get here with klass == Derived and found == FALSE
+ */
+ /* but it shouldn't be the case that if we're looking
+ * for the definition and didn't find a result; the
+ * loop above should've taken us as far as we could
+ * go! */
+ g_assert (!(definition && !found));
+ if (!found)
+ goto retry;
+ }
+
+ g_assert (result != NULL);
+ return result;
+}
#include "mono/utils/atomic.h"
#include "mono/utils/mono-error.h"
#include "mono/utils/mono-error-internals.h"
-#include "mono/io-layer/io-layer.h"
#include <string.h>
#include <errno.h>
+#include <mono/utils/w32api.h>
#if defined(HOST_WIN32)
#include <oleauto.h>
MonoBoolean
ves_icall_System_ConsoleDriver_Isatty (HANDLE handle)
{
- return (GetFileType (handle) == FILE_TYPE_CHAR);
+ return mono_w32file_get_type (handle) == FILE_TYPE_CHAR;
}
MonoBoolean
#include <mono/metadata/threadpool.h>
#include <mono/utils/mono-signal-handler.h>
#include <mono/utils/mono-proclib.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
/* On solaris, curses.h must come before both termios.h and term.h */
#ifdef HAVE_CURSES_H
#include <glib.h>
#include <string.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/mono-path.h>
+#include "utils/w32api.h"
#include "cil-coff.h"
#include "metadata-internals.h"
#include "image.h"
#ifdef HOST_WIN32
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/mono-compiler.h>
+#include <mono/utils/w32api.h>
#include "image.h"
#define STATUS_SUCCESS 0x00000000L
#include <mono/metadata/w32semaphore.h>
#include <mono/metadata/w32event.h>
#include <mono/metadata/w32process.h>
+#include <mono/metadata/w32file.h>
#include <metadata/threads.h>
#include <metadata/profiler-private.h>
#include <mono/metadata/coree.h>
-#include <mono/io-layer/io-layer.h>
//#define DEBUG_DOMAIN_UNLOAD 1
#ifndef HOST_WIN32
mono_w32handle_init ();
mono_w32handle_namespace_init ();
- wapi_init ();
#endif
mono_w32mutex_init ();
mono_w32semaphore_init ();
mono_w32event_init ();
mono_w32process_init ();
+ mono_w32file_init ();
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters_init ();
mono_coop_mutex_destroy (&appdomains_mutex);
mono_w32process_cleanup ();
-
-#ifndef HOST_WIN32
- wapi_cleanup ();
-#endif
+ mono_w32file_cleanup ();
}
void
#include <mono/metadata/environment.h>
#include <mono/metadata/exception.h>
#include <mono/utils/mono-compiler.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
+++ /dev/null
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MONO_FILE_IO_INTERNALS_H__
-#define __MONO_FILE_IO_INTERNALS_H__
-
-#include <config.h>
-#include <glib.h>
-#include "mono/metadata/object.h"
-#include "mono/metadata/object-internals.h"
-
-gboolean
-mono_file_io_move_file (gunichar2 *path, gunichar2 *dest, gint32 *error);
-
-gboolean
-mono_file_io_copy_file (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error);
-
-gint64
-mono_file_io_get_file_size (HANDLE handle, gint32 *error);
-
-gboolean
-mono_file_io_lock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error);
-
-gboolean
-mono_file_io_replace_file (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
- gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error);
-
-gboolean
-mono_file_io_unlock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error);
-
-HANDLE
-mono_file_io_get_console_output (void);
-
-HANDLE
-mono_file_io_get_console_error (void);
-
-HANDLE
-mono_file_io_get_console_input (void);
-
-#endif /* __MONO_FILE_IO_INTERNALS_H__ */
+++ /dev/null
-/*
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef _MONO_METADATA_FILEIO_WINDOWS_H_
-#define _MONO_METADATA_FILEIO_WINDOWS_H_
-
-#include <config.h>
-#include <glib.h>
-
-#ifdef HOST_WIN32
-#include "mono/metadata/file-io.h"
-#include "mono/metadata/file-io-internals.h"
-#endif /* HOST_WIN32 */
-#endif /* _MONO_METADATA_FILEIO_WINDOWS_H_ */
+++ /dev/null
-/*
- * file-io-windows-uwp.c: UWP file-io support for Mono.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
-*/
-#include <config.h>
-#include <glib.h>
-#include "mono/utils/mono-compiler.h"
-
-#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
-#include <windows.h>
-#include "mono/metadata/file-io-windows-internals.h"
-
-gboolean
-mono_file_io_move_file (gunichar2 *path, gunichar2 *dest, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = MoveFileEx (path, dest, MOVEFILE_COPY_ALLOWED);
- if (result == FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-
-gboolean
-mono_file_io_replace_file (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
- gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
- if (result == FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-
-gboolean
-mono_file_io_copy_file (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
-{
- gboolean result = FALSE;
- COPYFILE2_EXTENDED_PARAMETERS copy_param = {0};
-
- copy_param.dwSize = sizeof (COPYFILE2_EXTENDED_PARAMETERS);
- copy_param.dwCopyFlags = (!overwrite) ? COPY_FILE_FAIL_IF_EXISTS : 0;
-
- MONO_ENTER_GC_SAFE;
-
- result = SUCCEEDED (CopyFile2 (path, dest, ©_param));
- if (result == FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-
-gint64
-mono_file_io_get_file_size (HANDLE handle, gint32 *error)
-{
- LARGE_INTEGER length;
-
- MONO_ENTER_GC_SAFE;
-
- if (!GetFileSizeEx (handle, &length)) {
- *error=GetLastError ();
- length.QuadPart = INVALID_FILE_SIZE;
- }
-
- MONO_EXIT_GC_SAFE;
- return length.QuadPart;
-}
-
-gboolean
-mono_file_io_lock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = LockFile (handle, position & 0xFFFFFFFF, position >> 32,
- length & 0xFFFFFFFF, length >> 32);
-
- if (result == FALSE) {
- *error = GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-
-gboolean
-mono_file_io_unlock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
- length & 0xFFFFFFFF, length >> 32);
-
- if (result == FALSE) {
- *error = GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-
-HANDLE
-mono_file_io_get_console_output (void)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetStdHandle (STD_OUTPUT_HANDLE)");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_OUTPUT_HANDLE)");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return INVALID_HANDLE_VALUE;
-}
-
-HANDLE
-mono_file_io_get_console_input (void)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetStdHandle (STD_INPUT_HANDLE)");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_INPUT_HANDLE)");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return INVALID_HANDLE_VALUE;
-}
-
-HANDLE
-mono_file_io_get_console_error (void)
-{
- MonoError mono_error;
- mono_error_init (&mono_error);
-
- g_unsupported_api ("GetStdHandle (STD_ERROR_HANDLE)");
-
- mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_ERROR_HANDLE)");
- mono_error_set_pending_exception (&mono_error);
-
- SetLastError (ERROR_NOT_SUPPORTED);
-
- return INVALID_HANDLE_VALUE;
-}
-
-#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
-
-MONO_EMPTY_SOURCE_FILE (file_io_windows_uwp);
-#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+++ /dev/null
-/*
- * file-io-windows.c: Windows File IO internal calls.
- *
- * Copyright 2016 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#include <config.h>
-#include <glib.h>
-
-#if defined(HOST_WIN32)
-#include <winsock2.h>
-#include <windows.h>
-#include "mono/metadata/file-io-windows-internals.h"
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
-{
- return (gunichar2) ':'; /* colon */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
-{
- return (gunichar2) '\\'; /* backslash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
-{
- return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_PathSeparator ()
-{
- return (gunichar2) ';'; /* semicolon */
-}
-
-void ves_icall_System_IO_MonoIO_DumpHandles (void)
-{
- return;
-}
-#endif /* HOST_WIN32 */
+++ /dev/null
-/*
- * file-io.c: File IO internal calls
- *
- * Author:
- * Dick Porter (dick@ximian.com)
- * Gonzalo Paniagua Javier (gonzalo@ximian.com)
- *
- * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#include <config.h>
-
-#include <glib.h>
-#include <string.h>
-#include <errno.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
-#include <mono/metadata/file-io.h>
-#include <mono/metadata/file-io-internals.h>
-#include <mono/metadata/exception.h>
-#include <mono/metadata/appdomain.h>
-#include <mono/metadata/marshal.h>
-#include <mono/utils/strenc.h>
-#include <utils/mono-io-portability.h>
-#include <mono/metadata/w32handle.h>
-
-#undef DEBUG
-
-/* conversion functions */
-
-static guint32 convert_mode(MonoFileMode mono_mode)
-{
- guint32 mode;
-
- switch(mono_mode) {
- case FileMode_CreateNew:
- mode=CREATE_NEW;
- break;
- case FileMode_Create:
- mode=CREATE_ALWAYS;
- break;
- case FileMode_Open:
- mode=OPEN_EXISTING;
- break;
- case FileMode_OpenOrCreate:
- mode=OPEN_ALWAYS;
- break;
- case FileMode_Truncate:
- mode=TRUNCATE_EXISTING;
- break;
- case FileMode_Append:
- mode=OPEN_ALWAYS;
- break;
- default:
- g_warning("System.IO.FileMode has unknown value 0x%x",
- mono_mode);
- /* Safe fallback */
- mode=OPEN_EXISTING;
- }
-
- return(mode);
-}
-
-static guint32 convert_access(MonoFileAccess mono_access)
-{
- guint32 access;
-
- switch(mono_access) {
- case FileAccess_Read:
- access=GENERIC_READ;
- break;
- case FileAccess_Write:
- access=GENERIC_WRITE;
- break;
- case FileAccess_ReadWrite:
- access=GENERIC_READ|GENERIC_WRITE;
- break;
- default:
- g_warning("System.IO.FileAccess has unknown value 0x%x",
- mono_access);
- /* Safe fallback */
- access=GENERIC_READ;
- }
-
- return(access);
-}
-
-static guint32 convert_share(MonoFileShare mono_share)
-{
- guint32 share = 0;
-
- if (mono_share & FileShare_Read) {
- share |= FILE_SHARE_READ;
- }
- if (mono_share & FileShare_Write) {
- share |= FILE_SHARE_WRITE;
- }
- if (mono_share & FileShare_Delete) {
- share |= FILE_SHARE_DELETE;
- }
-
- if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) {
- g_warning("System.IO.FileShare has unknown value 0x%x",
- mono_share);
- /* Safe fallback */
- share=0;
- }
-
- return(share);
-}
-
-#if 0
-static guint32 convert_stdhandle(guint32 fd)
-{
- guint32 stdhandle;
-
- switch(fd) {
- case 0:
- stdhandle=STD_INPUT_HANDLE;
- break;
- case 1:
- stdhandle=STD_OUTPUT_HANDLE;
- break;
- case 2:
- stdhandle=STD_ERROR_HANDLE;
- break;
- default:
- g_warning("unknown standard file descriptor %d", fd);
- stdhandle=STD_INPUT_HANDLE;
- }
-
- return(stdhandle);
-}
-#endif
-
-static guint32 convert_seekorigin(MonoSeekOrigin origin)
-{
- guint32 w32origin;
-
- switch(origin) {
- case SeekOrigin_Begin:
- w32origin=FILE_BEGIN;
- break;
- case SeekOrigin_Current:
- w32origin=FILE_CURRENT;
- break;
- case SeekOrigin_End:
- w32origin=FILE_END;
- break;
- default:
- g_warning("System.IO.SeekOrigin has unknown value 0x%x",
- origin);
- /* Safe fallback */
- w32origin=FILE_CURRENT;
- }
-
- return(w32origin);
-}
-
-static gint64 convert_filetime (const FILETIME *filetime)
-{
- guint64 ticks = filetime->dwHighDateTime;
- ticks <<= 32;
- ticks += filetime->dwLowDateTime;
- return (gint64)ticks;
-}
-
-static void convert_win32_file_attribute_data (const WIN32_FILE_ATTRIBUTE_DATA *data, MonoIOStat *stat)
-{
- stat->attributes = data->dwFileAttributes;
- stat->creation_time = convert_filetime (&data->ftCreationTime);
- stat->last_access_time = convert_filetime (&data->ftLastAccessTime);
- stat->last_write_time = convert_filetime (&data->ftLastWriteTime);
- stat->length = ((gint64)data->nFileSizeHigh << 32) | data->nFileSizeLow;
-}
-
-/* Managed file attributes have nearly but not quite the same values
- * as the w32 equivalents.
- */
-static guint32 convert_attrs(MonoFileAttributes attrs)
-{
- if(attrs & FileAttributes_Encrypted) {
- attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
- }
-
- return(attrs);
-}
-
-/*
- * On Win32, GetFileAttributes|Ex () seems to try opening the file,
- * which might lead to sharing violation errors, whereas FindFirstFile
- * always succeeds. These 2 wrappers resort to FindFirstFile if
- * GetFileAttributes|Ex () has failed.
- */
-static guint32
-get_file_attributes (const gunichar2 *path)
-{
- guint32 res;
- WIN32_FIND_DATA find_data;
- HANDLE find_handle;
- gint32 error;
-
- res = GetFileAttributes (path);
- if (res != -1)
- return res;
-
- error = GetLastError ();
-
- if (error != ERROR_SHARING_VIOLATION)
- return res;
-
- find_handle = FindFirstFile (path, &find_data);
-
- if (find_handle == INVALID_HANDLE_VALUE)
- return res;
-
- FindClose (find_handle);
-
- return find_data.dwFileAttributes;
-}
-
-static gboolean
-get_file_attributes_ex (const gunichar2 *path, WIN32_FILE_ATTRIBUTE_DATA *data)
-{
- gboolean res;
- WIN32_FIND_DATA find_data;
- HANDLE find_handle;
- gint32 error;
-
- res = GetFileAttributesEx (path, GetFileExInfoStandard, data);
- if (res)
- return TRUE;
-
- error = GetLastError ();
-
- if (error != ERROR_SHARING_VIOLATION)
- return FALSE;
-
- find_handle = FindFirstFile (path, &find_data);
-
- if (find_handle == INVALID_HANDLE_VALUE)
- return FALSE;
-
- FindClose (find_handle);
-
- data->dwFileAttributes = find_data.dwFileAttributes;
- data->ftCreationTime = find_data.ftCreationTime;
- data->ftLastAccessTime = find_data.ftLastAccessTime;
- data->ftLastWriteTime = find_data.ftLastWriteTime;
- data->nFileSizeHigh = find_data.nFileSizeHigh;
- data->nFileSizeLow = find_data.nFileSizeLow;
-
- return TRUE;
-}
-
-/* System.IO.MonoIO internal calls */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=CreateDirectory (mono_string_chars (path), NULL);
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=RemoveDirectory (mono_string_chars (path));
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-static gchar *
-get_search_dir (const gunichar2 *pattern)
-{
- gchar *p;
- gchar *result;
-
- p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
- result = g_path_get_dirname (p);
- g_free (p);
- return result;
-}
-
-static GPtrArray *
-get_filesystem_entries (const gunichar2 *path,
- const gunichar2 *path_with_pattern,
- gint attrs, gint mask,
- gint32 *error)
-{
- int i;
- WIN32_FIND_DATA data;
- HANDLE find_handle;
- GPtrArray *names = NULL;
- gchar *utf8_path = NULL, *utf8_result, *full_name;
- gint32 attributes;
-
- mask = convert_attrs ((MonoFileAttributes)mask);
- attributes = get_file_attributes (path);
- if (attributes != -1) {
- if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
- *error = ERROR_INVALID_NAME;
- goto fail;
- }
- } else {
- *error = GetLastError ();
- goto fail;
- }
-
- find_handle = FindFirstFile (path_with_pattern, &data);
- if (find_handle == INVALID_HANDLE_VALUE) {
- gint32 find_error = GetLastError ();
-
- if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
- /* No files, so just return an empty array */
- goto fail;
- }
-
- *error = find_error;
- goto fail;
- }
-
- utf8_path = get_search_dir (path_with_pattern);
- names = g_ptr_array_new ();
-
- do {
- if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
- (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
- continue;
- }
-
- if ((data.dwFileAttributes & mask) == attrs) {
- utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
- if (utf8_result == NULL) {
- continue;
- }
-
- full_name = g_build_filename (utf8_path, utf8_result, NULL);
- g_ptr_array_add (names, full_name);
-
- g_free (utf8_result);
- }
- } while(FindNextFile (find_handle, &data));
-
- if (FindClose (find_handle) == FALSE) {
- *error = GetLastError ();
- goto fail;
- }
-
- g_free (utf8_path);
- return names;
-fail:
- if (names) {
- for (i = 0; i < names->len; i++)
- g_free (g_ptr_array_index (names, i));
- g_ptr_array_free (names, TRUE);
- }
- g_free (utf8_path);
- return FALSE;
-}
-
-
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
- MonoString *path_with_pattern,
- gint attrs, gint mask,
- gint32 *ioerror)
-{
- MonoError error;
- MonoDomain *domain = mono_domain_get ();
- MonoArray *result;
- int i;
- GPtrArray *names;
-
- *ioerror = ERROR_SUCCESS;
-
- MONO_ENTER_GC_SAFE;
- names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
- MONO_EXIT_GC_SAFE;
-
- if (!names) {
- // If there's no array and no error, then return an empty array.
- if (*ioerror == ERROR_SUCCESS) {
- MonoArray *arr = mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
- mono_error_set_pending_exception (&error);
- return arr;
- }
- return NULL;
- }
-
- result = mono_array_new_checked (domain, mono_defaults.string_class, names->len, &error);
- if (mono_error_set_pending_exception (&error))
- goto leave;
- for (i = 0; i < names->len; i++) {
- mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
- g_free (g_ptr_array_index (names, i));
- }
-leave:
- g_ptr_array_free (names, TRUE);
- return result;
-}
-
-typedef struct {
- MonoDomain *domain;
- gchar *utf8_path;
- HANDLE find_handle;
-} IncrementalFind;
-
-static gboolean
-incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
-{
- gchar *utf8_result;
- gchar *full_name;
-
- if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
- return FALSE;
-
- utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
- if (utf8_result == NULL)
- return FALSE;
-
- full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
- g_free (utf8_result);
- *result = mono_string_new (mono_domain_get (), full_name);
- g_free (full_name);
-
- return TRUE;
-}
-
-HANDLE
-ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
-{
- HANDLE hnd;
- WIN32_FIND_DATA data;
- MonoError error;
-
- hnd = FindFirstFile (mono_string_chars (path_with_pattern), &data);
-
- if (hnd == INVALID_HANDLE_VALUE) {
- *file_name = NULL;
- *file_attr = 0;
- *ioerror = GetLastError ();
- return hnd;
- }
-
- mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
- mono_error_set_pending_exception (&error);
-
- *file_attr = data.dwFileAttributes;
- *ioerror = ERROR_SUCCESS;
-
- return hnd;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
-{
- MonoBoolean res;
- WIN32_FIND_DATA data;
- MonoError error;
-
- res = FindNextFile (hnd, &data);
-
- if (res == FALSE) {
- *file_name = NULL;
- *file_attr = 0;
- *ioerror = GetLastError ();
- return res;
- }
-
- mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
- mono_error_set_pending_exception (&error);
-
- *file_attr = data.dwFileAttributes;
- *ioerror = ERROR_SUCCESS;
-
- return res;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
-{
- return FindClose (hnd);
-}
-
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
- MonoString *path_with_pattern,
- gint32 *result_attr, gint32 *ioerror,
- gpointer *handle)
-{
- MonoError error;
- WIN32_FIND_DATA data;
- HANDLE find_handle;
- IncrementalFind *ifh;
- MonoString *result;
-
- *ioerror = ERROR_SUCCESS;
-
- find_handle = FindFirstFile (mono_string_chars (path_with_pattern), &data);
-
- if (find_handle == INVALID_HANDLE_VALUE) {
- gint32 find_error = GetLastError ();
- *handle = NULL;
-
- if (find_error == ERROR_FILE_NOT_FOUND)
- return NULL;
-
- *ioerror = find_error;
- return NULL;
- }
-
- ifh = g_new (IncrementalFind, 1);
- ifh->find_handle = find_handle;
- ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
- if (mono_error_set_pending_exception (&error)) {
- MONO_ENTER_GC_SAFE;
- FindClose (find_handle);
- MONO_EXIT_GC_SAFE;
- g_free (ifh);
- return NULL;
- }
- ifh->domain = mono_domain_get ();
- *handle = ifh;
-
- while (incremental_find_check_match (ifh, &data, &result) == 0){
- if (FindNextFile (find_handle, &data) == FALSE){
- int e = GetLastError ();
- if (e != ERROR_NO_MORE_FILES)
- *ioerror = e;
- return NULL;
- }
- }
- *result_attr = data.dwFileAttributes;
-
- return result;
-}
-
-/* FIXME make gc suspendable */
-MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
-{
- IncrementalFind *ifh = (IncrementalFind *)handle;
- WIN32_FIND_DATA data;
- MonoString *result;
-
- *error = ERROR_SUCCESS;
- do {
- if (FindNextFile (ifh->find_handle, &data) == FALSE){
- int e = GetLastError ();
- if (e != ERROR_NO_MORE_FILES)
- *error = e;
- return NULL;
- }
- } while (incremental_find_check_match (ifh, &data, &result) == 0);
-
- *result_attr = data.dwFileAttributes;
- return result;
-}
-
-int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
-{
- IncrementalFind *ifh = (IncrementalFind *)handle;
- gint32 error;
-
- MONO_ENTER_GC_SAFE;
- if (FindClose (ifh->find_handle) == FALSE){
- error = GetLastError ();
- } else
- error = ERROR_SUCCESS;
- g_free (ifh->utf8_path);
- g_free (ifh);
- MONO_EXIT_GC_SAFE;
-
- return error;
-}
-
-MonoString *
-ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
-{
- MonoError error;
- MonoString *result;
- gunichar2 *buf;
- int len, res_len;
-
- len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
- buf = g_new (gunichar2, len);
-
- mono_error_init (&error);
- *io_error=ERROR_SUCCESS;
- result = NULL;
-
- res_len = GetCurrentDirectory (len, buf);
- if (res_len > len) { /*buf is too small.*/
- int old_res_len = res_len;
- g_free (buf);
- buf = g_new (gunichar2, res_len);
- res_len = GetCurrentDirectory (res_len, buf) == old_res_len;
- }
-
- if (res_len) {
- len = 0;
- while (buf [len])
- ++ len;
-
- result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
- } else {
- *io_error=GetLastError ();
- }
-
- g_free (buf);
- mono_error_set_pending_exception (&error);
- return result;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
- gint32 *error)
-{
- gboolean ret;
-
- *error=ERROR_SUCCESS;
-
- ret=SetCurrentDirectory (mono_string_chars (path));
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- return(ret);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_move_file (gunichar2 *path, gunichar2 *dest, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = MoveFile (path, dest);
- if (result == FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-#endif /* HAVE_CLASSIC_WINAPI_SUPPORT */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, gint32 *error)
-{
- *error=ERROR_SUCCESS;
- return mono_file_io_move_file (mono_string_chars (path), mono_string_chars (dest), error);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_replace_file (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
- gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
- if (result == FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-#endif /* HAVE_CLASSIC_WINAPI_SUPPORT */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
- MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
- gint32 *error)
-{
- gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
- guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
-
- if (sourceFileName)
- utf16_sourceFileName = mono_string_chars (sourceFileName);
- if (destinationFileName)
- utf16_destinationFileName = mono_string_chars (destinationFileName);
- if (destinationBackupFileName)
- utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName);
-
- *error = ERROR_SUCCESS;
- if (ignoreMetadataErrors)
- replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
-
- /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
- return mono_file_io_replace_file (utf16_destinationFileName, utf16_sourceFileName,
- utf16_destinationBackupFileName, replaceFlags, error);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_copy_file (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = CopyFile (path, dest, !overwrite);
- if (result == FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-#endif /* HAVE_CLASSIC_WINAPI_SUPPORT */
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
- MonoBoolean overwrite, gint32 *error)
-{
- *error=ERROR_SUCCESS;
- return mono_file_io_copy_file (mono_string_chars (path), mono_string_chars (dest), overwrite, error);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=DeleteFile (mono_string_chars (path));
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-gint32
-ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
-{
- gint32 ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=get_file_attributes (mono_string_chars (path));
-
- /*
- * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
- * headers is wrong, hence this temporary workaround.
- * See
- * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
- */
- if (ret==-1) {
- /* if(ret==INVALID_FILE_ATTRIBUTES) { */
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
- gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=SetFileAttributes (mono_string_chars (path),
- convert_attrs ((MonoFileAttributes)attrs));
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-gint32
-ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=GetFileType (handle);
- if(ret==FILE_TYPE_UNKNOWN) {
- /* Not necessarily an error, but the caller will have
- * to decide based on the error value.
- */
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
- gint32 *error)
-{
- gboolean result;
- WIN32_FILE_ATTRIBUTE_DATA data;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- result = get_file_attributes_ex (mono_string_chars (path), &data);
-
- if (result) {
- convert_win32_file_attribute_data (&data, stat);
- } else {
- *error=GetLastError ();
- memset (stat, 0, sizeof (MonoIOStat));
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-
-HANDLE
-ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
- gint32 access_mode, gint32 share, gint32 options,
- gint32 *error)
-{
- HANDLE ret;
- int attributes, attrs;
- gunichar2 *chars;
- MONO_ENTER_GC_SAFE;
-
- chars = mono_string_chars (filename);
- *error=ERROR_SUCCESS;
-
- if (options != 0){
- if (options & FileOptions_Encrypted)
- attributes = FILE_ATTRIBUTE_ENCRYPTED;
- else
- attributes = FILE_ATTRIBUTE_NORMAL;
- if (options & FileOptions_DeleteOnClose)
- attributes |= FILE_FLAG_DELETE_ON_CLOSE;
- if (options & FileOptions_SequentialScan)
- attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
- if (options & FileOptions_RandomAccess)
- attributes |= FILE_FLAG_RANDOM_ACCESS;
-
- if (options & FileOptions_Temporary)
- attributes |= FILE_ATTRIBUTE_TEMPORARY;
-
- if (options & FileOptions_WriteThrough)
- attributes |= FILE_FLAG_WRITE_THROUGH;
- } else
- attributes = FILE_ATTRIBUTE_NORMAL;
-
- /* If we're opening a directory we need to set the extra flag
- */
- attrs = get_file_attributes (chars);
- if (attrs != INVALID_FILE_ATTRIBUTES) {
- if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
- attributes |= FILE_FLAG_BACKUP_SEMANTICS;
- }
- }
-
- ret=CreateFile (chars, convert_access ((MonoFileAccess)access_mode),
- convert_share ((MonoFileShare)share), NULL, convert_mode ((MonoFileMode)mode),
- attributes, NULL);
- if(ret==INVALID_HANDLE_VALUE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=CloseHandle (handle);
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-gint32
-ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
- gint32 dest_offset, gint32 count,
- gint32 *error)
-{
- guchar *buffer;
- gboolean result;
- guint32 n;
-
- *error=ERROR_SUCCESS;
-
- MONO_CHECK_ARG_NULL (dest, 0);
-
- if (dest_offset > mono_array_length (dest) - count) {
- mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
- return 0;
- }
-
- buffer = mono_array_addr (dest, guchar, dest_offset);
-
- MONO_ENTER_GC_SAFE;
- result = ReadFile (handle, buffer, count, &n, NULL);
- MONO_EXIT_GC_SAFE;
-
- if (!result) {
- *error=GetLastError ();
- return -1;
- }
-
- return (gint32)n;
-}
-
-gint32
-ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
- gint32 src_offset, gint32 count,
- gint32 *error)
-{
- guchar *buffer;
- gboolean result;
- guint32 n;
-
- *error=ERROR_SUCCESS;
-
- MONO_CHECK_ARG_NULL (src, 0);
-
- if (src_offset > mono_array_length (src) - count) {
- mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
- return 0;
- }
-
- buffer = mono_array_addr (src, guchar, src_offset);
- MONO_ENTER_GC_SAFE;
- result = WriteFile (handle, buffer, count, &n, NULL);
- MONO_EXIT_GC_SAFE;
-
- if (!result) {
- *error=GetLastError ();
- return -1;
- }
-
- return (gint32)n;
-}
-
-gint64
-ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
- gint32 *error)
-{
- gint32 offset_hi;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- offset_hi = offset >> 32;
- offset = SetFilePointer (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
- convert_seekorigin ((MonoSeekOrigin)origin));
-
- if(offset==INVALID_SET_FILE_POINTER) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return offset | ((gint64)offset_hi << 32);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
-{
- gboolean ret;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- ret=FlushFileBuffers (handle);
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gint64
-mono_file_io_get_file_size (HANDLE handle, gint32 *error)
-{
- gint64 length;
- guint32 length_hi;
-
- MONO_ENTER_GC_SAFE;
-
- length = GetFileSize (handle, &length_hi);
- if(length==INVALID_FILE_SIZE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return length | ((gint64)length_hi << 32);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-gint64
-ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
-{
- *error=ERROR_SUCCESS;
- return mono_file_io_get_file_size (handle, error);
-}
-
-/* FIXME make gc suspendable */
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
- gint32 *error)
-{
- gint64 offset, offset_set;
- gint32 offset_hi;
- gint32 length_hi;
- gboolean result;
-
- *error=ERROR_SUCCESS;
-
- /* save file pointer */
-
- offset_hi = 0;
- offset = SetFilePointer (handle, 0, &offset_hi, FILE_CURRENT);
- if(offset==INVALID_SET_FILE_POINTER) {
- *error=GetLastError ();
- return(FALSE);
- }
-
- /* extend or truncate */
-
- length_hi = length >> 32;
- offset_set=SetFilePointer (handle, length & 0xFFFFFFFF, &length_hi,
- FILE_BEGIN);
- if(offset_set==INVALID_SET_FILE_POINTER) {
- *error=GetLastError ();
- return(FALSE);
- }
-
- result = SetEndOfFile (handle);
- if(result==FALSE) {
- *error=GetLastError ();
- return(FALSE);
- }
-
- /* restore file pointer */
-
- offset_set=SetFilePointer (handle, offset & 0xFFFFFFFF, &offset_hi,
- FILE_BEGIN);
- if(offset_set==INVALID_SET_FILE_POINTER) {
- *error=GetLastError ();
- return(FALSE);
- }
-
- return result;
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
- gint64 last_access_time,
- gint64 last_write_time, gint32 *error)
-{
- gboolean ret;
- const FILETIME *creation_filetime;
- const FILETIME *last_access_filetime;
- const FILETIME *last_write_filetime;
- MONO_ENTER_GC_SAFE;
-
- *error=ERROR_SUCCESS;
-
- if (creation_time < 0)
- creation_filetime = NULL;
- else
- creation_filetime = (FILETIME *)&creation_time;
-
- if (last_access_time < 0)
- last_access_filetime = NULL;
- else
- last_access_filetime = (FILETIME *)&last_access_time;
-
- if (last_write_time < 0)
- last_write_filetime = NULL;
- else
- last_write_filetime = (FILETIME *)&last_write_time;
-
- ret=SetFileTime (handle, creation_filetime, last_access_filetime, last_write_filetime);
- if(ret==FALSE) {
- *error=GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return(ret);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-mono_file_io_get_console_output (void)
-{
- return GetStdHandle (STD_OUTPUT_HANDLE);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-HANDLE
-ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
-{
- return mono_file_io_get_console_output ();
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-mono_file_io_get_console_input (void)
-{
- return GetStdHandle (STD_INPUT_HANDLE);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-HANDLE
-ves_icall_System_IO_MonoIO_get_ConsoleInput ()
-{
- return mono_file_io_get_console_input ();
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-HANDLE
-mono_file_io_get_console_error (void)
-{
- return GetStdHandle (STD_ERROR_HANDLE);
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-HANDLE
-ves_icall_System_IO_MonoIO_get_ConsoleError ()
-{
- return mono_file_io_get_console_error ();
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
-{
- SECURITY_ATTRIBUTES attr;
- gboolean ret;
-
- attr.nLength=sizeof(SECURITY_ATTRIBUTES);
- attr.bInheritHandle=TRUE;
- attr.lpSecurityDescriptor=NULL;
-
- MONO_ENTER_GC_SAFE;
- ret=CreatePipe (read_handle, write_handle, &attr, 0);
- MONO_EXIT_GC_SAFE;
-
- if(ret==FALSE) {
- *error = GetLastError ();
- /* FIXME: throw an exception? */
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-MonoBoolean
-ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
- HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
-{
- /* This is only used on Windows */
- gboolean ret;
-
- MONO_ENTER_GC_SAFE;
-#ifdef HOST_WIN32
- ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
-#else
- mono_w32handle_ref (source_handle);
- *target_handle = source_handle;
- ret = TRUE;
-#endif
- MONO_EXIT_GC_SAFE;
-
- if(ret==FALSE) {
- *error = GetLastError ();
- /* FIXME: throw an exception? */
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-#ifndef HOST_WIN32
-gunichar2
-ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
-{
- return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
-{
- return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
-{
- if (IS_PORTABILITY_SET)
- return (gunichar2) '\\'; /* backslash */
- else
- return (gunichar2) '/'; /* forward slash */
-}
-
-gunichar2
-ves_icall_System_IO_MonoIO_get_PathSeparator ()
-{
- return (gunichar2) ':'; /* colon */
-}
-#endif /* !HOST_WIN32 */
-
-static const gunichar2
-invalid_path_chars [] = {
-#if defined (TARGET_WIN32)
- 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
- 0x003c, /* less than */
- 0x003e, /* greater than */
- 0x007c, /* pipe */
- 0x0008,
- 0x0010,
- 0x0011,
- 0x0012,
- 0x0014,
- 0x0015,
- 0x0016,
- 0x0017,
- 0x0018,
- 0x0019,
-#endif
- 0x0000 /* null */
-};
-
-MonoArray *
-ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
-{
- MonoError error;
- MonoArray *chars;
- MonoDomain *domain;
- int i, n;
-
- domain = mono_domain_get ();
- n = sizeof (invalid_path_chars) / sizeof (gunichar2);
- chars = mono_array_new_checked (domain, mono_defaults.char_class, n, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < n; ++ i)
- mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
-
- return chars;
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_lock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = LockFile (handle, position & 0xFFFFFFFF, position >> 32,
- length & 0xFFFFFFFF, length >> 32);
-
- if (result == FALSE) {
- *error = GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
- gint64 length, gint32 *error)
-{
- *error=ERROR_SUCCESS;
- mono_file_io_lock_file (handle, position, length, error);
-}
-
-#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
-gboolean
-mono_file_io_unlock_file (HANDLE handle, gint64 position, gint64 length, gint32 *error)
-{
- gboolean result = FALSE;
- MONO_ENTER_GC_SAFE;
-
- result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
- length & 0xFFFFFFFF, length >> 32);
-
- if (result == FALSE) {
- *error = GetLastError ();
- }
-
- MONO_EXIT_GC_SAFE;
- return result;
-}
-#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
-
-void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
- gint64 length, gint32 *error)
-{
- *error=ERROR_SUCCESS;
- mono_file_io_unlock_file (handle, position, length, error);
-}
-
-//Support for io-layer free mmap'd files.
-
-#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
-
-gint64
-mono_filesize_from_path (MonoString *string)
-{
- MonoError error;
- struct stat buf;
- gint64 res;
- char *path = mono_string_to_utf8_checked (string, &error);
- mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
-
- MONO_ENTER_GC_SAFE;
- if (stat (path, &buf) == -1)
- res = -1;
- else
- res = (gint64)buf.st_size;
-
- g_free (path);
-
- MONO_EXIT_GC_SAFE;
- return res;
-}
-
-gint64
-mono_filesize_from_fd (int fd)
-{
- struct stat buf;
- int res;
-
- MONO_ENTER_GC_SAFE;
- res = fstat (fd, &buf);
- MONO_EXIT_GC_SAFE;
-
- if (res == -1)
- return (gint64)-1;
-
- return (gint64)buf.st_size;
-}
-
-#endif
-
-#ifndef HOST_WIN32
-void mono_w32handle_dump (void);
-
-void ves_icall_System_IO_MonoIO_DumpHandles (void)
-{
-
- mono_w32handle_dump ();
-}
-#endif /* !HOST_WIN32 */
+++ /dev/null
-/*
- * file-io.h: File IO internal calls
- *
- * Authors:
- * Dick Porter (dick@ximian.com)
- * Dan Lewis (dihlewis@yahoo.co.uk)
- *
- * (C) 2001 Ximian, Inc.
- * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-
-#ifndef _MONO_METADATA_FILEIO_H_
-#define _MONO_METADATA_FILEIO_H_
-
-#include <config.h>
-#include <glib.h>
-
-#include <mono/metadata/object-internals.h>
-#include <mono/utils/mono-compiler.h>
-
-G_BEGIN_DECLS
-
-/* This is a copy of System.IO.FileAccess */
-typedef enum {
- FileAccess_Read=0x01,
- FileAccess_Write=0x02,
- FileAccess_ReadWrite=FileAccess_Read|FileAccess_Write
-} MonoFileAccess;
-
-/* This is a copy of System.IO.FileMode */
-typedef enum {
- FileMode_CreateNew=1,
- FileMode_Create=2,
- FileMode_Open=3,
- FileMode_OpenOrCreate=4,
- FileMode_Truncate=5,
- FileMode_Append=6
-} MonoFileMode;
-
-/* This is a copy of System.IO.FileShare */
-typedef enum {
- FileShare_None=0x0,
- FileShare_Read=0x01,
- FileShare_Write=0x02,
- FileShare_ReadWrite=FileShare_Read|FileShare_Write,
- FileShare_Delete=0x04
-} MonoFileShare;
-
-/* This is a copy of System.IO.FileOptions */
-typedef enum {
- FileOptions_None = 0,
- FileOptions_Temporary = 1, // Internal. See note in System.IO.FileOptions
- FileOptions_Encrypted = 0x4000,
- FileOptions_DeleteOnClose = 0x4000000,
- FileOptions_SequentialScan = 0x8000000,
- FileOptions_RandomAccess = 0x10000000,
- FileOptions_Asynchronous = 0x40000000,
- FileOptions_WriteThrough = 0x80000000
-} MonoFileOptions;
-
-/* This is a copy of System.IO.SeekOrigin */
-typedef enum {
- SeekOrigin_Begin=0,
- SeekOrigin_Current=1,
- SeekOrigin_End=2
-} MonoSeekOrigin;
-
-/* This is a copy of System.IO.MonoIOStat */
-typedef struct _MonoIOStat {
- gint32 attributes;
- gint64 length;
- gint64 creation_time;
- gint64 last_access_time;
- gint64 last_write_time;
-} MonoIOStat;
-
-/* This is a copy of System.IO.FileAttributes */
-typedef enum {
- FileAttributes_ReadOnly=0x00001,
- FileAttributes_Hidden=0x00002,
- FileAttributes_System=0x00004,
- FileAttributes_Directory=0x00010,
- FileAttributes_Archive=0x00020,
- FileAttributes_Device=0x00040,
- FileAttributes_Normal=0x00080,
- FileAttributes_Temporary=0x00100,
- FileAttributes_SparseFile=0x00200,
- FileAttributes_ReparsePoint=0x00400,
- FileAttributes_Compressed=0x00800,
- FileAttributes_Offline=0x01000,
- FileAttributes_NotContentIndexed=0x02000,
- FileAttributes_Encrypted=0x04000,
- FileAttributes_MonoExecutable= (int) 0x80000000
-} MonoFileAttributes;
-/* This is not used anymore
-typedef struct _MonoFSAsyncResult {
- MonoObject obj;
- MonoObject *state;
- MonoBoolean completed;
- MonoBoolean done;
- MonoException *exc;
- MonoWaitHandle *wait_handle;
- MonoDelegate *async_callback;
- MonoBoolean completed_synch;
- MonoArray *buffer;
- gint offset;
- gint count;
- gint original_count;
- gint bytes_read;
- MonoDelegate *real_cb;
-} MonoFSAsyncResult;
-*/
-/* System.IO.MonoIO */
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error);
-
-MonoArray *
-ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
- MonoString *path_with_pattern,
- gint mask, gint attrs,
- gint32 *error);
-
-extern gpointer
-ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern,
- MonoString **file_name,
- gint32 *file_attr,
- gint32 *ioerror);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_FindNextFile (gpointer hnd,
- MonoString **file_name,
- gint32 *file_attr,
- gint32 *ioerror);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_FindCloseFile (gpointer hnd);
-
-extern MonoString *
-ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
- MonoString *path_with_pattern,
- gint32 *result_mask,
- gint32 *error,
- gpointer *handle);
-extern MonoString *
-ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_mask, gint32 *error);
-
-extern int
-ves_icall_System_IO_MonoIO_FindClose (gpointer handle);
-
-extern MonoString *
-ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
- gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
- gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
- MonoBoolean overwrite, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error);
-
-extern gint32
-ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
- gint32 *error);
-
-extern gint32
-ves_icall_System_IO_MonoIO_GetFileType (gpointer handle, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
- gint32 *error);
-
-extern gpointer
-ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
- gint32 access_mode, gint32 share, gint32 options,
- gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_Close (gpointer handle, gint32 *error);
-
-extern gint32
-ves_icall_System_IO_MonoIO_Read (gpointer handle, MonoArray *dest,
- gint32 dest_offset, gint32 count,
- gint32 *error);
-
-extern gint32
-ves_icall_System_IO_MonoIO_Write (gpointer handle, MonoArray *src,
- gint32 src_offset, gint32 count,
- gint32 *error);
-
-extern gint64
-ves_icall_System_IO_MonoIO_Seek (gpointer handle, gint64 offset, gint32 origin,
- gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_Flush (gpointer handle, gint32 *error);
-
-extern gint64
-ves_icall_System_IO_MonoIO_GetLength (gpointer handle, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetLength (gpointer handle, gint64 length,
- gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_SetFileTime (gpointer handle, gint64 creation_time,
- gint64 last_access_time,
- gint64 last_write_time, gint32 *error);
-
-extern gpointer
-ves_icall_System_IO_MonoIO_get_ConsoleOutput (void);
-
-extern gpointer
-ves_icall_System_IO_MonoIO_get_ConsoleInput (void);
-
-extern gpointer
-ves_icall_System_IO_MonoIO_get_ConsoleError (void);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_CreatePipe (gpointer *read_handle, gpointer *write_handle, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_DuplicateHandle (gpointer source_process_handle, gpointer source_handle,
- gpointer target_process_handle, gpointer *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error);
-
-extern gunichar2
-ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void);
-
-extern gunichar2
-ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void);
-
-extern gunichar2
-ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void);
-
-extern gunichar2
-ves_icall_System_IO_MonoIO_get_PathSeparator (void);
-
-extern MonoArray *
-ves_icall_System_IO_MonoIO_get_InvalidPathChars (void);
-
-extern void ves_icall_System_IO_MonoIO_Lock (gpointer handle, gint64 position,
- gint64 length, gint32 *error);
-extern void ves_icall_System_IO_MonoIO_Unlock (gpointer handle, gint64 position,
- gint64 length, gint32 *error);
-
-extern MonoBoolean
-ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
- MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
- gint32 *error);
-
-MONO_RT_EXTERNAL_ONLY
-extern gint64
-mono_filesize_from_path (MonoString *path);
-
-extern gint64
-mono_filesize_from_fd (int fd);
-
-void
-ves_icall_System_IO_MonoIO_DumpHandles (void);
-
-G_END_DECLS
-
-#endif /* _MONO_METADATA_FILEIO_H_ */
#include <mono/metadata/object.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
#include <mono/metadata/file-mmap.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/metadata/marshal.h>
#include <mono/utils/mono-dl.h>
#include <mono/utils/mono-io-portability.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/metadata/w32error.h>
#ifdef HOST_WIN32
#include <mono/utils/atomic.h>
#include <mono/utils/mono-coop-semaphore.h>
#include <mono/utils/hazard-pointer.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
#ifndef HOST_WIN32
#include <pthread.h>
HANDLES(ICALL(MODULE_13, "get_MetadataToken", ves_icall_reflection_get_token))
ICALL_TYPE(MCMETH, "System.Reflection.MonoCMethod", MCMETH_1)
-ICALL(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_MonoMethod_GetGenericMethodDefinition)
+HANDLES(ICALL(MCMETH_1, "GetGenericMethodDefinition_impl", ves_icall_MonoMethod_GetGenericMethodDefinition))
ICALL(MCMETH_2, "InternalInvoke", ves_icall_InternalInvoke)
-ICALL(MCMETH_3, "get_core_clr_security_level", ves_icall_MonoMethod_get_core_clr_security_level)
+HANDLES(ICALL(MCMETH_3, "get_core_clr_security_level", ves_icall_MonoMethod_get_core_clr_security_level))
ICALL_TYPE(MEVIN, "System.Reflection.MonoEventInfo", MEVIN_1)
ICALL(MEVIN_1, "get_event_info", ves_icall_MonoEventInfo_get_event_info)
ICALL(MFIELD_7, "get_core_clr_security_level", ves_icall_MonoField_get_core_clr_security_level)
ICALL_TYPE(MMETH, "System.Reflection.MonoMethod", MMETH_2)
-ICALL(MMETH_2, "GetGenericArguments", ves_icall_MonoMethod_GetGenericArguments)
-ICALL(MMETH_3, "GetGenericMethodDefinition_impl", ves_icall_MonoMethod_GetGenericMethodDefinition)
-ICALL(MMETH_11, "GetPInvoke", ves_icall_MonoMethod_GetPInvoke)
+HANDLES(ICALL(MMETH_2, "GetGenericArguments", ves_icall_MonoMethod_GetGenericArguments))
+HANDLES(ICALL(MMETH_3, "GetGenericMethodDefinition_impl", ves_icall_MonoMethod_GetGenericMethodDefinition))
+HANDLES(ICALL(MMETH_11, "GetPInvoke", ves_icall_MonoMethod_GetPInvoke))
ICALL(MMETH_4, "InternalInvoke", ves_icall_InternalInvoke)
-ICALL(MMETH_5, "MakeGenericMethod_impl", ves_icall_MonoMethod_MakeGenericMethod_impl)
-ICALL(MMETH_6, "get_IsGenericMethod", ves_icall_MonoMethod_get_IsGenericMethod)
-ICALL(MMETH_7, "get_IsGenericMethodDefinition", ves_icall_MonoMethod_get_IsGenericMethodDefinition)
-ICALL(MMETH_8, "get_base_method", ves_icall_MonoMethod_get_base_method)
-ICALL(MMETH_10, "get_core_clr_security_level", ves_icall_MonoMethod_get_core_clr_security_level)
-ICALL(MMETH_9, "get_name", ves_icall_MonoMethod_get_name)
+HANDLES(ICALL(MMETH_5, "MakeGenericMethod_impl", ves_icall_MonoMethod_MakeGenericMethod_impl))
+HANDLES(ICALL(MMETH_6, "get_IsGenericMethod", ves_icall_MonoMethod_get_IsGenericMethod))
+HANDLES(ICALL(MMETH_7, "get_IsGenericMethodDefinition", ves_icall_MonoMethod_get_IsGenericMethodDefinition))
+HANDLES(ICALL(MMETH_8, "get_base_method", ves_icall_MonoMethod_get_base_method))
+HANDLES(ICALL(MMETH_10, "get_core_clr_security_level", ves_icall_MonoMethod_get_core_clr_security_level))
+HANDLES(ICALL(MMETH_9, "get_name", ves_icall_MonoMethod_get_name))
ICALL_TYPE(MMETHI, "System.Reflection.MonoMethodInfo", MMETHI_4)
ICALL(MMETHI_4, "get_method_attributes", vell_icall_get_method_attributes)
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/exception-internals.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
#include <mono/metadata/console-io.h>
#include <mono/metadata/mono-route.h>
#include <mono/metadata/w32socket.h>
#include <mono/metadata/w32mutex.h>
#include <mono/metadata/w32semaphore.h>
#include <mono/metadata/w32event.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/monobitset.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/bsearch.h>
#include <mono/utils/mono-os-mutex.h>
#include <mono/utils/mono-threads.h>
+#include <mono/metadata/w32error.h>
+#include <mono/utils/w32api.h>
#include "decimal-ms.h"
#include "number-ms.h"
}
ICALL_EXPORT void
-ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
+ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethodHandle ref_method, int* flags, MonoStringHandleOut entry_point, MonoStringHandleOut dll_name, MonoError *error)
{
MonoDomain *domain = mono_domain_get ();
- MonoImage *image = method->method->klass->image;
- MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
+ MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
+ MonoImage *image = method->klass->image;
+ MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
MonoTableInfo *tables = image->tables;
MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
const char *import = NULL;
const char *scope = NULL;
+ mono_error_init (error);
+
if (image_is_dynamic (image)) {
MonoReflectionMethodAux *method_aux =
- (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
+ (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method);
if (method_aux) {
import = method_aux->dllentry;
scope = method_aux->dll;
}
if (!import || !scope) {
- mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
+ mono_error_set_argument (error, "method", "System.Refleciton.Emit method with invalid pinvoke information");
return;
}
}
}
*flags = piinfo->piflags;
- *entry_point = mono_string_new (domain, import);
- *dll_name = mono_string_new (domain, scope);
+ MONO_HANDLE_ASSIGN (entry_point, mono_string_new_handle (domain, import, error));
+ return_if_nok (error);
+ MONO_HANDLE_ASSIGN (dll_name, mono_string_new_handle (domain, scope, error));
}
-ICALL_EXPORT MonoReflectionMethod *
-ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
+ICALL_EXPORT MonoReflectionMethodHandle
+ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethodHandle ref_method, MonoError *error)
{
- MonoMethodInflated *imethod;
- MonoMethod *result;
- MonoReflectionMethod *ret = NULL;
- MonoError error;
+ mono_error_init (error);
+ MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- if (method->method->is_generic)
- return method;
+ if (method->is_generic)
+ return ref_method;
- if (!method->method->is_inflated)
- return NULL;
+ if (!method->is_inflated)
+ return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- imethod = (MonoMethodInflated *) method->method;
+ MonoMethodInflated *imethod = (MonoMethodInflated *) method;
- result = imethod->declaring;
+ MonoMethod *result = imethod->declaring;
/* Not a generic method. */
if (!result->is_generic)
- return NULL;
+ return MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE);
- if (image_is_dynamic (method->method->klass->image)) {
- MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
- MonoReflectionMethod *res;
+ if (image_is_dynamic (method->klass->image)) {
+ MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
/*
* FIXME: Why is this stuff needed at all ? Why can't the code below work for
* the dynamic case as well ?
*/
mono_image_lock ((MonoImage*)image);
- res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
+ MonoReflectionMethodHandle res = MONO_HANDLE_NEW (MonoReflectionMethod, mono_g_hash_table_lookup (image->generic_def_objects, imethod));
mono_image_unlock ((MonoImage*)image);
- if (res)
+ if (!MONO_HANDLE_IS_NULL (res))
return res;
}
MonoClass *klass = ((MonoMethod *) imethod)->klass;
/*Generic methods gets the context of the GTD.*/
if (mono_class_get_context (klass)) {
- result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
- if (!mono_error_ok (&error))
- goto leave;
+ result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), error);
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
}
}
- ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
-leave:
- if (!mono_error_ok (&error))
- mono_error_set_pending_exception (&error);
- return ret;
+ return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (ref_method), result, NULL, error);
}
ICALL_EXPORT gboolean
-ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
+ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethodHandle ref_method, MonoError *erro)
{
- return mono_method_signature (method->method)->generic_param_count != 0;
+ MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
+ return mono_method_signature (method)->generic_param_count != 0;
}
ICALL_EXPORT gboolean
-ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
+ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethodHandle ref_method, MonoError *Error)
{
- return method->method->is_generic;
+ MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
+ return method->is_generic;
}
-ICALL_EXPORT MonoArray*
-ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
+static gboolean
+set_array_generic_argument_handle_inflated (MonoDomain *domain, MonoGenericInst *inst, int i, MonoArrayHandle arr, MonoError *error)
{
- MonoError error;
- MonoReflectionType *rt;
- MonoArray *res;
- MonoDomain *domain;
- int count, i;
+ HANDLE_FUNCTION_ENTER ();
+ mono_error_init (error);
+ MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, inst->type_argv [i], error);
+ if (!is_ok (error))
+ goto leave;
+ MONO_HANDLE_ARRAY_SETREF (arr, i, rt);
+leave:
+ HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
+}
- domain = mono_object_domain (method);
+static gboolean
+set_array_generic_argument_handle_gparam (MonoDomain *domain, MonoGenericContainer *container, int i, MonoArrayHandle arr, MonoError *error)
+{
+ HANDLE_FUNCTION_ENTER ();
+ mono_error_init (error);
+ MonoGenericParam *param = mono_generic_container_get_param (container, i);
+ MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
+ MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, &pklass->byval_arg, error);
+ if (!is_ok (error))
+ goto leave;
+ MONO_HANDLE_ARRAY_SETREF (arr, i, rt);
+leave:
+ HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
+}
+
+ICALL_EXPORT MonoArrayHandle
+ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethodHandle ref_method, MonoError *error)
+{
+ mono_error_init (error);
+ MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_method);
+ MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
- if (method->method->is_inflated) {
- MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
+ if (method->is_inflated) {
+ MonoGenericInst *inst = mono_method_get_context (method)->method_inst;
if (inst) {
- count = inst->type_argc;
- res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < count; i++) {
- rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ int count = inst->type_argc;
+ MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
- mono_array_setref (res, i, rt);
+ for (int i = 0; i < count; i++) {
+ if (!set_array_generic_argument_handle_inflated (domain, inst, i, res, error))
+ break;
}
-
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
return res;
}
}
- count = mono_method_signature (method->method)->generic_param_count;
- res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
-
- for (i = 0; i < count; i++) {
- MonoGenericContainer *container = mono_method_get_generic_container (method->method);
- MonoGenericParam *param = mono_generic_container_get_param (container, i);
- MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
-
- rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ int count = mono_method_signature (method)->generic_param_count;
+ MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.systemtype_class, count, error);
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
- mono_array_setref (res, i, rt);
+ MonoGenericContainer *container = mono_method_get_generic_container (method);
+ for (int i = 0; i < count; i++) {
+ if (!set_array_generic_argument_handle_gparam (domain, container, i, res, error))
+ break;
}
-
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
return res;
}
}
ICALL_EXPORT int
-ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
+ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethodHandle rfield, MonoError *error)
{
- MonoMethod *method = rfield->method;
+ mono_error_init (error);
+ MonoMethod *method = MONO_HANDLE_GETVAL (rfield, method);
return mono_security_core_clr_method_level (method, TRUE);
}
ptr = buf;
while (size > initial_size) {
- size = (guint) GetLogicalDriveStrings (initial_size, ptr);
+ size = (guint) mono_w32file_get_logical_drive (initial_size, ptr);
if (size > initial_size) {
if (ptr != buf)
g_free (ptr);
MonoError error;
gunichar2 volume_name [MAX_PATH + 1];
- if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
+ if (mono_w32file_get_volume_information (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
return NULL;
MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
mono_error_set_pending_exception (&error);
gint32 *error)
{
gboolean result;
- ULARGE_INTEGER wapi_free_bytes_avail;
- ULARGE_INTEGER wapi_total_number_of_bytes;
- ULARGE_INTEGER wapi_total_number_of_free_bytes;
*error = ERROR_SUCCESS;
- result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
- &wapi_total_number_of_free_bytes);
- if (result) {
- *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
- *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
- *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
- } else {
- *free_bytes_avail = 0;
- *total_number_of_bytes = 0;
- *total_number_of_free_bytes = 0;
- *error = GetLastError ();
- }
+ result = mono_w32file_get_disk_free_space (mono_string_chars (path_name), free_bytes_avail, total_number_of_bytes, total_number_of_free_bytes);
+ if (!result)
+ *error = mono_w32error_get_last ();
return result;
}
static inline guint32
mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
{
- return GetDriveType (mono_string_chars (root_path_name));
+ return mono_w32file_get_drive_type (mono_string_chars (root_path_name));
}
#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
return MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (domain, klass, error));
}
-ICALL_EXPORT MonoReflectionMethod *
-ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
+ICALL_EXPORT MonoReflectionMethodHandle
+ves_icall_MonoMethod_get_base_method (MonoReflectionMethodHandle m, gboolean definition, MonoError *error)
{
- MonoReflectionMethod *ret = NULL;
- MonoError error;
-
- MonoClass *klass, *parent;
- MonoGenericContext *generic_inst = NULL;
- MonoMethod *method = m->method;
- MonoMethod *result = NULL;
- int slot;
-
- if (method->klass == NULL)
- return m;
-
- if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
- MONO_CLASS_IS_INTERFACE (method->klass) ||
- method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
- return m;
-
- slot = mono_method_get_vtable_slot (method);
- if (slot == -1)
- return m;
-
- klass = method->klass;
- if (mono_class_is_ginst (klass)) {
- generic_inst = mono_class_get_context (klass);
- klass = mono_class_get_generic_class (klass)->container_class;
- }
-
-retry:
- if (definition) {
- /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
- for (parent = klass->parent; parent != NULL; parent = parent->parent) {
- /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
- or klass is the generic container class and generic_inst is the instantiation.
-
- when we go to the parent, if the parent is an open constructed type, we need to
- replace the type parameters by the definitions from the generic_inst, and then take it
- apart again into the klass and the generic_inst.
-
- For cases like this:
- class C<T> : B<T, int> {
- public override void Foo () { ... }
- }
- class B<U,V> : A<HashMap<U,V>> {
- public override void Foo () { ... }
- }
- class A<X> {
- public virtual void Foo () { ... }
- }
-
- if at each iteration the parent isn't open, we can skip inflating it. if at some
- iteration the parent isn't generic (after possible inflation), we set generic_inst to
- NULL;
- */
- MonoGenericContext *parent_inst = NULL;
- if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
- parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- }
- if (mono_class_is_ginst (parent)) {
- parent_inst = mono_class_get_context (parent);
- parent = mono_class_get_generic_class (parent)->container_class;
- }
-
- mono_class_setup_vtable (parent);
- if (parent->vtable_size <= slot)
- break;
- klass = parent;
- generic_inst = parent_inst;
- }
- } else {
- klass = klass->parent;
- if (!klass)
- return m;
- if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
- klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
-
- generic_inst = NULL;
- }
- if (mono_class_is_ginst (klass)) {
- generic_inst = mono_class_get_context (klass);
- klass = mono_class_get_generic_class (klass)->container_class;
- }
-
- }
-
- if (generic_inst) {
- klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
- }
-
- if (klass == method->klass)
- return m;
+ mono_error_init (error);
+ MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
- /*This is possible if definition == FALSE.
- * Do it here to be really sure we don't read invalid memory.
- */
- if (slot >= klass->vtable_size)
+ MonoMethod *base = mono_method_get_base_method (method, definition, error);
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
+ if (base == method)
return m;
-
- mono_class_setup_vtable (klass);
-
- result = klass->vtable [slot];
- if (result == NULL) {
- /* It is an abstract method */
- gboolean found = FALSE;
- gpointer iter = NULL;
- while ((result = mono_class_get_methods (klass, &iter))) {
- if (result->slot == slot) {
- found = TRUE;
- break;
- }
- }
- /* found might be FALSE if we looked in an abstract class
- * that doesn't override an abstract method of its
- * parent:
- * abstract class Base {
- * public abstract void Foo ();
- * }
- * abstract class Derived : Base { }
- * class Child : Derived {
- * public override void Foo () { }
- * }
- *
- * if m was Child.Foo and we ask for the base method,
- * then we get here with klass == Derived and found == FALSE
- */
- /* but it shouldn't be the case that if we're looking
- * for the definition and didn't find a result; the
- * loop above should've taken us as far as we could
- * go! */
- g_assert (!(definition && !found));
- if (!found)
- goto retry;
- }
-
- g_assert (result != NULL);
-
- ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
- mono_error_set_pending_exception (&error);
- return ret;
+ else
+ return mono_method_get_object_handle (mono_domain_get (), base, NULL, error);
}
-ICALL_EXPORT MonoString*
-ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
+ICALL_EXPORT MonoStringHandle
+ves_icall_MonoMethod_get_name (MonoReflectionMethodHandle m, MonoError *error)
{
- MonoMethod *method = m->method;
+ mono_error_init (error);
+ MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
- MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
- return m->name;
+ MonoStringHandle s = mono_string_new_handle (MONO_HANDLE_DOMAIN (m), method->name, error);
+ if (!is_ok (error))
+ return NULL_HANDLE_STRING;
+ MONO_HANDLE_SET (m, name, s);
+ return s;
}
ICALL_EXPORT void
#include "loader.h"
#include "marshal.h"
#include "coree.h"
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/checked-build.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/mono-path.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#include <mono/metadata/w32error.h>
#define INVALID_ADDRESS 0xffffffff
fname_utf16 = g_utf8_to_utf16 (absfname, -1, NULL, NULL, NULL);
module_handle = MonoLoadImage (fname_utf16);
if (status && module_handle == NULL)
- last_error = GetLastError ();
+ last_error = mono_w32error_get_last ();
/* mono_image_open_from_module_handle is called by _CorDllMain. */
image = g_hash_table_lookup (loaded_images, absfname);
#include <execinfo.h>
#endif
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/mono-compiler.h>
#include "lock-tracer.h"
#include <mono/metadata/threads-types.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/threads.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/metadata/object-internals.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/profiler-private.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/atomic.h>
+#include <mono/utils/w32api.h>
/*
* Pull the list of opcodes
/* Orphaned events left by aborted threads */
while (new_->wait_list) {
LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d): Closing orphaned event %d", mono_thread_info_get_small_id (), new_->wait_list->data));
- CloseHandle (new_->wait_list->data);
+ mono_w32event_close (new_->wait_list->data);
new_->wait_list = g_slist_remove (new_->wait_list, new_->wait_list->data);
}
}
/* This looks superfluous */
if (mono_thread_current_check_pending_interrupt ()) {
- CloseHandle (event);
+ mono_w32event_close (event);
return FALSE;
}
*/
mon->wait_list = g_slist_remove (mon->wait_list, event);
}
- CloseHandle (event);
+ mono_w32event_close (event);
return success;
}
#include "utils/mono-networkinterfaces.h"
#include "utils/mono-error-internals.h"
#include "utils/atomic.h"
-#include <mono/io-layer/io-layer.h>
/* map of CounterSample.cs */
struct _MonoCounterSample {
#include <mono/metadata/object-internals.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/security.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/utils/strenc.h>
#ifndef HOST_WIN32
int
mono_runtime_try_exec_main (MonoMethod *method, MonoArray *args, MonoObject **exc);
-MonoReflectionMethod*
-ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types);
+MonoReflectionMethodHandle
+ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethodHandle rmethod, MonoArrayHandle types, MonoError *error);
gint32
ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, gboolean create_open_instance, MonoError *error);
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-threads-coop.h>
#include "cominterop.h"
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
static void
get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error);
#include "mono/metadata/domain-internals.h"
#include "mono/metadata/gc-internals.h"
#include "mono/metadata/mono-config-dirs.h"
-#include "mono/io-layer/io-layer.h"
#include "mono/utils/mono-dl.h"
#include <mono/utils/mono-logger-internals.h>
#include <string.h>
return mono_generic_class_get_class (gclass);
}
-static MonoReflectionMethod*
-reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types, MonoError *error)
+static MonoGenericInst*
+generic_inst_from_type_array_handle (MonoArrayHandle types, MonoError *error)
+{
+ HANDLE_FUNCTION_ENTER ();
+ mono_error_init (error);
+ MonoGenericInst *ginst = NULL;
+ int count = mono_array_handle_length (types);
+ MonoType **type_argv = g_new0 (MonoType *, count);
+ MonoReflectionTypeHandle garg = MONO_HANDLE_NEW (MonoReflectionType, NULL);
+ for (int i = 0; i < count; i++) {
+ MONO_HANDLE_ARRAY_GETREF (garg, types, i);
+ type_argv [i] = mono_reflection_type_handle_mono_type (garg, error);
+ if (!is_ok (error))
+ goto leave;
+
+ }
+ ginst = mono_metadata_get_generic_inst (count, type_argv);
+leave:
+ g_free (type_argv);
+ HANDLE_FUNCTION_RETURN_VAL (ginst);
+}
+
+static MonoMethod*
+reflection_bind_generic_method_parameters (MonoMethod *method, MonoArrayHandle types, MonoError *error)
{
MonoClass *klass;
- MonoMethod *method, *inflated;
- MonoMethodInflated *imethod;
+ MonoMethod *inflated;
MonoGenericContext tmp_context;
- MonoGenericInst *ginst;
- MonoType **type_argv;
- int count, i;
mono_error_init (error);
- g_assert (strcmp (rmethod->object.vtable->klass->name, "MethodBuilder"));
-
- method = rmethod->method;
-
klass = method->klass;
if (method->is_inflated)
method = ((MonoMethodInflated *) method)->declaring;
- count = mono_method_signature (method)->generic_param_count;
- if (count != mono_array_length (types))
+ int count = mono_method_signature (method)->generic_param_count;
+ if (count != mono_array_handle_length (types)) {
+ mono_error_set_argument (error, "typeArguments", "Incorrect number of generic arguments");
return NULL;
-
- type_argv = g_new0 (MonoType *, count);
- for (i = 0; i < count; i++) {
- MonoReflectionType *garg = (MonoReflectionType *)mono_array_get (types, gpointer, i);
- type_argv [i] = mono_reflection_type_get_handle (garg, error);
- if (!is_ok (error)) {
- g_free (type_argv);
- return NULL;
- }
}
- ginst = mono_metadata_get_generic_inst (count, type_argv);
- g_free (type_argv);
+
+ MonoGenericInst *ginst = generic_inst_from_type_array_handle (types, error);
+ return_val_if_nok (error, NULL);
tmp_context.class_inst = mono_class_is_ginst (klass) ? mono_class_get_generic_class (klass)->context.class_inst : NULL;
tmp_context.method_inst = ginst;
inflated = mono_class_inflate_generic_method_checked (method, &tmp_context, error);
mono_error_assert_ok (error);
- imethod = (MonoMethodInflated *) inflated;
+
+ if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
+ mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
+ return NULL;
+ }
+
+ return inflated;
+}
+
+MonoReflectionMethodHandle
+ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethodHandle rmethod, MonoArrayHandle types, MonoError *error)
+{
+ mono_error_init (error);
+ g_assert (0 != strcmp (mono_handle_class (rmethod)->name, "MethodBuilder"));
+
+ MonoMethod *method = MONO_HANDLE_GETVAL (rmethod, method);
+ MonoMethod *imethod = reflection_bind_generic_method_parameters (method, types, error);
+ return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
/*FIXME but I think this is no longer necessary*/
if (image_is_dynamic (method->klass->image)) {
* to the reflection objects representing their generic definitions.
*/
mono_image_lock ((MonoImage*)image);
- mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
+ mono_g_hash_table_insert (image->generic_def_objects, imethod, MONO_HANDLE_RAW (rmethod));
mono_image_unlock ((MonoImage*)image);
}
- if (!mono_verifier_is_method_valid_generic_instantiation (inflated)) {
- mono_error_set_argument (error, "typeArguments", "Invalid generic arguments");
- return NULL;
- }
-
- return mono_method_get_object_checked (mono_object_domain (rmethod), inflated, NULL, error);
-}
-
-MonoReflectionMethod*
-ves_icall_MonoMethod_MakeGenericMethod_impl (MonoReflectionMethod *rmethod, MonoArray *types)
-{
- MonoError error;
- MonoReflectionMethod *result = reflection_bind_generic_method_parameters (rmethod, types, &error);
- mono_error_set_pending_exception (&error);
- return result;
+ return mono_method_get_object_handle (MONO_HANDLE_DOMAIN (rmethod), imethod, NULL, error);
}
#include "mono/metadata/security-manager.h"
#include "mono/metadata/tabledefs.h"
#include "mono/metadata/tokentype.h"
+#include "mono/metadata/w32file.h"
+#include "mono/metadata/w32error.h"
#include "mono/utils/checked-build.h"
#include "mono/utils/mono-digest.h"
#include "mono/utils/mono-error-internals.h"
-
-#include "mono/io-layer/io-layer.h"
+#include "mono/utils/w32api.h"
#define TEXT_OFFSET 512
#define CLI_H_SIZE 136
checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
{
guint32 dummy;
- if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
- g_error ("WriteFile returned %d\n", GetLastError ());
+ if (!mono_w32file_write (f, buffer, numbytes, &dummy))
+ g_error ("mono_w32file_write returned %d\n", mono_w32error_get_last ());
}
/*
if (!assembly->sections [i].size)
continue;
- if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- g_error ("SetFilePointer returned %d\n", GetLastError ());
+ if (mono_w32file_seek (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ g_error ("mono_w32file_seek returned %d\n", mono_w32error_get_last ());
switch (i) {
case MONO_SECTION_TEXT:
}
/* check that the file is properly padded */
- if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
- g_error ("SetFilePointer returned %d\n", GetLastError ());
- if (! SetEndOfFile (file))
- g_error ("SetEndOfFile returned %d\n", GetLastError ());
+ if (mono_w32file_seek (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ g_error ("mono_w32file_seek returned %d\n", mono_w32error_get_last ());
+ if (! mono_w32file_truncate (file))
+ g_error ("mono_w32file_truncate returned %d\n", mono_w32error_get_last ());
mono_dynamic_stream_reset (&assembly->code);
mono_dynamic_stream_reset (&assembly->us);
#include "mono/metadata/tokentype.h"
#include "mono/utils/checked-build.h"
#include "mono/utils/mono-digest.h"
-#include "mono/io-layer/io-layer.h"
+#include "mono/utils/w32api.h"
static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, System.Runtime.InteropServices, MarshalAsAttribute);
static GENERATE_GET_CLASS_WITH_CACHE (module_builder, System.Reflection.Emit, ModuleBuilder);
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-lazy-init.h>
#include <mono/utils/mono-logger-internals.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
typedef struct {
gboolean (*init) (gint wakeup_pipe_fd);
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-rand.h>
#include <mono/utils/refcount.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
#define CPU_USAGE_LOW 80
#define CPU_USAGE_HIGH 95
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/refcount.h>
-#include <mono/io-layer/io-layer.h>
typedef struct {
MonoDomain *domain;
g_assert(wait_event);
MonoWaitHandle *wait_handle = mono_wait_handle_new (mono_object_domain (ares), wait_event, error);
if (!is_ok (error)) {
- CloseHandle (wait_event);
+ mono_w32event_close (wait_event);
return NULL;
}
MONO_OBJECT_SETREF (ares, handle, (MonoObject*) wait_handle);
#define SPECIAL_STATIC_THREAD 1
#define SPECIAL_STATIC_CONTEXT 2
-#ifdef HOST_WIN32
-typedef SECURITY_ATTRIBUTES WapiSecurityAttributes;
-#endif
-
typedef struct _MonoInternalThread MonoInternalThread;
typedef void (*MonoThreadCleanupFunc) (MonoNativeThreadId tid);
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/runtime.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/metadata/object-internals.h>
#include <mono/metadata/mono-debug-debugger.h>
#include <mono/utils/monobitset.h>
#include <mono/metadata/gc-internals.h>
#include <mono/metadata/reflection-internals.h>
#include <mono/metadata/abi-details.h>
+#include <mono/metadata/w32error.h>
+#include <mono/utils/w32api.h>
#ifdef HAVE_SIGNAL_H
#include <signal.h>
mono_threads_lock ();
mono_g_hash_table_remove (threads_starting_up, thread);
mono_threads_unlock ();
- mono_error_set_execution_engine (error, "Couldn't create thread. Error 0x%x", GetLastError());
+ mono_error_set_execution_engine (error, "Couldn't create thread. Error 0x%x", mono_w32error_get_last());
/* ref is not going to be decremented in start_wrapper_internal */
InterlockedDecrement (&start_info->ref);
ret = FALSE;
--- /dev/null
+
+#include "w32error.h"
+
+#include "utils/mono-lazy-init.h"
+
+static mono_lazy_init_t error_key_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+
+static pthread_key_t error_key;
+
+static void
+error_key_init (void)
+{
+ gint ret;
+ ret = pthread_key_create (&error_key, NULL);
+ g_assert (ret == 0);
+}
+
+guint32
+mono_w32error_get_last (void)
+{
+ mono_lazy_initialize (&error_key_once, error_key_init);
+ return GPOINTER_TO_UINT (pthread_getspecific (error_key));
+}
+
+void
+mono_w32error_set_last (guint32 error)
+{
+ gint ret;
+ mono_lazy_initialize (&error_key_once, error_key_init);
+ ret = pthread_setspecific (error_key, GUINT_TO_POINTER (error));
+ g_assert (ret == 0);
+}
+
+guint32
+mono_w32error_unix_to_win32 (guint32 error)
+{
+ /* mapping ideas borrowed from wine. they may need some work */
+
+ switch (error) {
+ case EACCES:
+ case EPERM:
+ case EROFS: return ERROR_ACCESS_DENIED;
+ case EAGAIN: return ERROR_SHARING_VIOLATION;
+ case EBUSY: return ERROR_LOCK_VIOLATION;
+ case EEXIST: return ERROR_FILE_EXISTS;
+ case EINVAL:
+ case ESPIPE: return ERROR_SEEK;
+ case EISDIR: return ERROR_CANNOT_MAKE;
+ case ENFILE:
+ case EMFILE: return ERROR_TOO_MANY_OPEN_FILES;
+ case ENOENT:
+ case ENOTDIR: return ERROR_FILE_NOT_FOUND;
+ case ENOSPC: return ERROR_HANDLE_DISK_FULL;
+ case ENOTEMPTY: return ERROR_DIR_NOT_EMPTY;
+ case ENOEXEC: return ERROR_BAD_FORMAT;
+ case ENAMETOOLONG: return ERROR_FILENAME_EXCED_RANGE;
+#ifdef EINPROGRESS
+ case EINPROGRESS: return ERROR_IO_PENDING;
+#endif
+ case ENOSYS: return ERROR_NOT_SUPPORTED;
+ case EBADF: return ERROR_INVALID_HANDLE;
+ case EIO: return ERROR_INVALID_HANDLE;
+ case EINTR: return ERROR_IO_PENDING; /* best match I could find */
+ case EPIPE: return ERROR_WRITE_FAULT;
+ default:
+ g_error ("%s: unknown error (%d) \"%s\"", error, g_strerror (error));
+ }
+}
--- /dev/null
+
+#include <windows.h>
+
+#include "w32error.h"
+
+guint32
+mono_w32error_get_last (void)
+{
+ return GetLastError ();
+}
+
+void
+mono_w32error_set_last (guint32 error)
+{
+ SetLastError (error);
+}
+
+guint32
+mono_w32error_unix_to_win32 (guint32 error)
+{
+ g_assert_not_reached ();
+}
--- /dev/null
+
+#ifndef _MONO_METADATA_W32ERROR_H_
+#define _MONO_METADATA_W32ERROR_H_
+
+#include <config.h>
+#include <glib.h>
+
+#if !defined(HOST_WIN32)
+
+#define ERROR_SUCCESS 0
+#define ERROR_FILE_NOT_FOUND 2
+#define ERROR_PATH_NOT_FOUND 3
+#define ERROR_TOO_MANY_OPEN_FILES 4
+#define ERROR_ACCESS_DENIED 5
+#define ERROR_INVALID_HANDLE 6
+#define ERROR_NOT_ENOUGH_MEMORY 8
+#define ERROR_BAD_FORMAT 11
+#define ERROR_INVALID_ACCESS 12
+#define ERROR_INVALID_DATA 13
+#define ERROR_OUTOFMEMORY 14
+#define ERROR_NOT_SAME_DEVICE 17
+#define ERROR_NO_MORE_FILES 18
+#define ERROR_BAD_LENGTH 24
+#define ERROR_SEEK 25
+#define ERROR_WRITE_FAULT 29
+#define ERROR_GEN_FAILURE 31
+#define ERROR_SHARING_VIOLATION 32
+#define ERROR_LOCK_VIOLATION 33
+#define ERROR_HANDLE_DISK_FULL 39
+#define ERROR_NOT_SUPPORTED 50
+#define ERROR_FILE_EXISTS 80
+#define ERROR_CANNOT_MAKE 82
+#define ERROR_INVALID_PARAMETER 87
+#define ERROR_INVALID_NAME 123
+#define ERROR_PROC_NOT_FOUND 127
+#define ERROR_DIR_NOT_EMPTY 145
+#define ERROR_ALREADY_EXISTS 183
+#define ERROR_BAD_EXE_FORMAT 193
+#define ERROR_FILENAME_EXCED_RANGE 206
+#define ERROR_DIRECTORY 267
+#define ERROR_IO_PENDING 997
+#define ERROR_ENCRYPTION_FAILED 6000
+#define WSAEINTR 10004
+#define WSAEBADF 10009
+#define WSAEACCES 10013
+#define WSAEFAULT 10014
+#define WSAEINVAL 10022
+#define WSAEMFILE 10024
+#define WSAEWOULDBLOCK 10035
+#define WSAEINPROGRESS 10036
+#define WSAEALREADY 10037
+#define WSAENOTSOCK 10038
+#define WSAEDESTADDRREQ 10039
+#define WSAEMSGSIZE 10040
+#define WSAENOPROTOOPT 10042
+#define WSAEPROTONOSUPPORT 10043
+#define WSAESOCKTNOSUPPORT 10044
+#define WSAEOPNOTSUPP 10045
+#define WSAEAFNOSUPPORT 10047
+#define WSAEADDRINUSE 10048
+#define WSAEADDRNOTAVAIL 10049
+#define WSAENETDOWN 10050
+#define WSAENETUNREACH 10051
+#define WSAECONNRESET 10054
+#define WSAENOBUFS 10055
+#define WSAEISCONN 10056
+#define WSAENOTCONN 10057
+#define WSAESHUTDOWN 10058
+#define WSAETIMEDOUT 10060
+#define WSAECONNREFUSED 10061
+#define WSAEHOSTDOWN 10064
+#define WSAEHOSTUNREACH 10065
+#define WSASYSCALLFAILURE 10107
+
+#endif
+
+guint32
+mono_w32error_get_last (void);
+
+void
+mono_w32error_set_last (guint32 error);
+
+guint32
+mono_w32error_unix_to_win32 (guint32 error);
+
+#endif /* _MONO_METADATA_W32ERROR_H_ */
#include "w32event.h"
+#include "w32error.h"
#include "w32handle-namespace.h"
-#include "mono/io-layer/io-layer.h"
#include "mono/utils/mono-logger-internals.h"
#include "mono/metadata/w32handle.h"
+#define MAX_PATH 260
+
typedef struct {
gboolean manual;
guint32 set_count;
return handle;
}
+gboolean
+mono_w32event_close (gpointer handle)
+{
+ return mono_w32handle_close (handle);
+}
+
void
mono_w32event_set (gpointer handle)
{
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating %s handle",
__func__, mono_w32handle_get_typename (type));
- SetLastError (ERROR_GEN_FAILURE);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
return NULL;
}
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different object. */
handle = NULL;
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
} else if (handle) {
/* Not an error, but this is how the caller is informed that the event wasn't freshly created */
- SetLastError (ERROR_ALREADY_EXISTS);
+ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
/* mono_w32handle_namespace_search_handle already adds a ref to the handle */
} else {
/* Need to blow away any old errors here, because code tests
* for ERROR_ALREADY_EXISTS on success (!) to see if an event
* was freshly created */
- SetLastError (ERROR_SUCCESS);
+ mono_w32error_set_last (ERROR_SUCCESS);
event = name ? namedevent_create (manual, initial, mono_string_chars (name)) : event_create (manual, initial);
- *error = GetLastError ();
+ *error = mono_w32error_get_last ();
return event;
}
MonoW32HandleEvent *event_handle;
if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return(FALSE);
}
case MONO_W32HANDLE_NAMEDEVENT:
break;
default:
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
MonoW32HandleType type;
MonoW32HandleEvent *event_handle;
- SetLastError (ERROR_SUCCESS);
+ mono_w32error_set_last (ERROR_SUCCESS);
if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return(FALSE);
}
case MONO_W32HANDLE_NAMEDEVENT:
break;
default:
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
void
ves_icall_System_Threading_Events_CloseEvent_internal (gpointer handle)
{
- CloseHandle (handle);
+ mono_w32handle_close (handle);
}
gpointer
return CreateEvent (NULL, manual, initial, NULL);
}
+gboolean
+mono_w32event_close (gpointer handle)
+{
+ return CloseHandle (handle);
+}
+
void
mono_w32event_set (gpointer handle)
{
gpointer
mono_w32event_create (gboolean manual, gboolean initial);
+gboolean
+mono_w32event_close (gpointer handle);
+
void
mono_w32event_set (gpointer handle);
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef _MONO_METADATA_W32FILE_INTERNALS_H_
+#define _MONO_METADATA_W32FILE_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#endif /* _MONO_METADATA_W32FILE_INTERNALS_H_ */
--- /dev/null
+/* $OpenBSD: glob.c,v 1.26 2005/11/28 17:50:12 deraadt Exp $ */
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * mono_w32file_unix_glob(3) -- a subset of the one defined in POSIX 1003.2.
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "w32file-unix-glob.h"
+
+#define EOS '\0'
+#define NOT '!'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define STAR '*'
+
+#ifndef DEBUG
+
+#define M_QUOTE 0x8000
+#define M_PROTECT 0x4000
+#define M_MASK 0xffff
+#define M_ASCII 0x00ff
+
+typedef unsigned short Char;
+
+#else
+
+#define M_QUOTE 0x80
+#define M_PROTECT 0x40
+#define M_MASK 0xff
+#define M_ASCII 0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((gchar)((c)&M_ASCII))
+#define META(c) ((gchar)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_ONE META('?')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+
+static int
+g_Ctoc(const gchar *, char *, unsigned int);
+
+static int
+glob0(GDir *dir, const gchar *, mono_w32file_unix_glob_t *, gboolean, gboolean);
+static int
+glob1(GDir *dir, gchar *, gchar *, mono_w32file_unix_glob_t *, size_t *, gboolean, gboolean);
+
+static int
+glob3(GDir *dir, gchar *, gchar *, mono_w32file_unix_glob_t *, size_t *, gboolean, gboolean);
+
+static int
+globextend(const gchar *, mono_w32file_unix_glob_t *, size_t *);
+
+static int
+match(const gchar *, gchar *, gchar *, gboolean);
+
+#ifdef DEBUG_ENABLED
+static void qprintf(const char *, Char *);
+#endif
+
+int
+mono_w32file_unix_glob(GDir *dir, const char *pattern, int flags, mono_w32file_unix_glob_t *pglob)
+{
+ const unsigned char *patnext;
+ int c;
+ gchar *bufnext, *bufend, patbuf[PATH_MAX];
+
+ patnext = (unsigned char *) pattern;
+ if (!(flags & W32FILE_UNIX_GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ pglob->gl_offs = 0;
+ }
+ pglob->gl_flags = flags & ~W32FILE_UNIX_GLOB_MAGCHAR;
+
+ bufnext = patbuf;
+ bufend = bufnext + PATH_MAX - 1;
+
+ /* Protect the quoted characters. */
+ while (bufnext < bufend && (c = *patnext++) != EOS)
+ if (c == QUOTE) {
+ if ((c = *patnext++) == EOS) {
+ c = QUOTE;
+ --patnext;
+ }
+ *bufnext++ = c | M_PROTECT;
+ } else
+ *bufnext++ = c;
+
+ *bufnext = EOS;
+
+ return glob0(dir, patbuf, pglob, flags & W32FILE_UNIX_GLOB_IGNORECASE,
+ flags & W32FILE_UNIX_GLOB_UNIQUE);
+}
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred. It is not an error
+ * to find no matches.
+ */
+static int
+glob0(GDir *dir, const gchar *pattern, mono_w32file_unix_glob_t *pglob, gboolean ignorecase,
+ gboolean unique)
+{
+ const gchar *qpatnext;
+ int c, err, oldpathc;
+ gchar *bufnext, patbuf[PATH_MAX];
+ size_t limit = 0;
+
+ qpatnext = pattern;
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case QUESTION:
+ pglob->gl_flags |= W32FILE_UNIX_GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= W32FILE_UNIX_GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG_ENABLED
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(dir, patbuf, patbuf+PATH_MAX-1, pglob, &limit,
+ ignorecase, unique)) != 0)
+ return(err);
+
+ if (pglob->gl_pathc == oldpathc) {
+ return(W32FILE_UNIX_GLOB_NOMATCH);
+ }
+
+ return(0);
+}
+
+static int
+glob1(GDir *dir, gchar *pattern, gchar *pattern_last, mono_w32file_unix_glob_t *pglob,
+ size_t *limitp, gboolean ignorecase, gboolean unique)
+{
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return(0);
+ return(glob3(dir, pattern, pattern_last, pglob, limitp, ignorecase,
+ unique));
+}
+
+static gboolean contains (mono_w32file_unix_glob_t *pglob, const gchar *name)
+{
+ int i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp) {
+ if (*pp) {
+ if (!strcmp (*pp, name)) {
+ return(TRUE);
+ }
+ }
+ }
+ }
+
+ return(FALSE);
+}
+
+static int
+glob3(GDir *dir, gchar *pattern, gchar *pattern_last, mono_w32file_unix_glob_t *pglob,
+ size_t *limitp, gboolean ignorecase, gboolean unique)
+{
+ const gchar *name;
+
+ /* Search directory for matching names. */
+ while ((name = g_dir_read_name(dir))) {
+ if (!match(name, pattern, pattern + strlen (pattern),
+ ignorecase)) {
+ continue;
+ }
+ if (!unique ||
+ !contains (pglob, name)) {
+ globextend (name, pglob, limitp);
+ }
+ }
+
+ return(0);
+}
+
+
+/*
+ * Extend the gl_pathv member of a mono_w32file_unix_glob_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the mono_w32file_unix_glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const gchar *path, mono_w32file_unix_glob_t *pglob, size_t *limitp)
+{
+ char **pathv;
+ int i;
+ unsigned int newsize, len;
+ char *copy;
+ const gchar *p;
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ /* FIXME: Can just use realloc(). */
+ pathv = (char **)(pglob->gl_pathv ? g_realloc ((char *)pglob->gl_pathv, newsize) :
+ g_malloc (newsize));
+ if (pathv == NULL) {
+ if (pglob->gl_pathv) {
+ g_free (pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+ return(W32FILE_UNIX_GLOB_NOSPACE);
+ }
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs; --i >= 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ ;
+ len = (size_t)(p - path);
+ *limitp += len;
+ if ((copy = (char *)malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ g_free (copy);
+ return(W32FILE_UNIX_GLOB_NOSPACE);
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+#if 0
+ /* Broken on opensuse 11 */
+ if ((pglob->gl_flags & W32FILE_UNIX_GLOB_LIMIT) &&
+ newsize + *limitp >= ARG_MAX) {
+ errno = 0;
+ return(W32FILE_UNIX_GLOB_NOSPACE);
+ }
+#endif
+
+ return(copy == NULL ? W32FILE_UNIX_GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(const gchar *name, gchar *pat, gchar *patend, gboolean ignorecase)
+{
+ gchar c;
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return(1);
+ do {
+ if (match(name, pat, patend, ignorecase))
+ return(1);
+ } while (*name++ != EOS);
+ return(0);
+ case M_ONE:
+ if (*name++ == EOS)
+ return(0);
+ break;
+ default:
+ if (ignorecase) {
+ if (g_ascii_tolower (*name++) != g_ascii_tolower (c))
+ return(0);
+ } else {
+ if (*name++ != c)
+ return(0);
+ }
+
+ break;
+ }
+ }
+ return(*name == EOS);
+}
+
+/* Free allocated data belonging to a mono_w32file_unix_glob_t structure. */
+void
+mono_w32file_unix_globfree(mono_w32file_unix_glob_t *pglob)
+{
+ int i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ g_free (*pp);
+ g_free (pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+
+static int
+g_Ctoc(const gchar *str, char *buf, unsigned int len)
+{
+
+ while (len--) {
+ if ((*buf++ = *str++) == EOS)
+ return (0);
+ }
+ return (1);
+}
+
+#ifdef DEBUG_ENABLED
+static void
+qprintf(const char *str, Char *s)
+{
+ Char *p;
+
+ (void)printf("%s:\n", str);
+ for (p = s; *p; p++)
+ (void)printf("%c", CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", ismeta(*p) ? '_' : ' ');
+ (void)printf("\n");
+}
+#endif
--- /dev/null
+/* $OpenBSD: glob.h,v 1.10 2005/12/13 00:35:22 millert Exp $ */
+/* $NetBSD: glob.h,v 1.5 1994/10/26 00:55:56 cgd Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef __MONO_METADATA_W32FILE_UNIX_GLOB_H__
+#define __MONO_METADATA_W32FILE_UNIX_GLOB_H__
+
+#include <glib.h>
+
+struct stat;
+typedef struct {
+ int gl_pathc; /* Count of total paths so far. */
+ int gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char **gl_pathv; /* List of paths matching pattern. */
+} mono_w32file_unix_glob_t;
+
+#define W32FILE_UNIX_GLOB_APPEND 0x0001 /* Append to output from previous call. */
+#define W32FILE_UNIX_GLOB_UNIQUE 0x0040 /* When appending only add items that aren't already in the list */
+#define W32FILE_UNIX_GLOB_NOSPACE (-1) /* Malloc call failed. */
+#define W32FILE_UNIX_GLOB_ABORTED (-2) /* Unignored error. */
+#define W32FILE_UNIX_GLOB_NOMATCH (-3) /* No match and W32FILE_UNIX_GLOB_NOCHECK not set. */
+#define W32FILE_UNIX_GLOB_NOSYS (-4) /* Function not supported. */
+
+#define W32FILE_UNIX_GLOB_MAGCHAR 0x0100 /* Pattern had globbing characters. */
+#define W32FILE_UNIX_GLOB_LIMIT 0x2000 /* Limit pattern match output to ARG_MAX */
+#define W32FILE_UNIX_GLOB_IGNORECASE 0x4000 /* Ignore case when matching */
+#define W32FILE_UNIX_GLOB_ABEND W32FILE_UNIX_GLOB_ABORTED /* backward compatibility */
+
+G_BEGIN_DECLS
+
+int
+mono_w32file_unix_glob (GDir *dir, const char *, int, mono_w32file_unix_glob_t *);
+
+void
+mono_w32file_unix_globfree (mono_w32file_unix_glob_t *);
+
+G_END_DECLS
+
+#endif /* !__MONO_METADATA_W32FILE_UNIX_GLOB_H__ */
--- /dev/null
+
+#include <config.h>
+#include <glib.h>
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
+#if defined(HAVE_SYS_STATFS_H)
+#include <sys/statfs.h>
+#endif
+#if defined(HAVE_SYS_PARAM_H) && defined(HAVE_SYS_MOUNT_H)
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#include <sys/types.h>
+#include <stdio.h>
+#include <utime.h>
+#ifdef __linux__
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <mono/utils/linux_magic.h>
+#endif
+#include <sys/time.h>
+#ifdef HAVE_DIRENT_H
+# include <dirent.h>
+#endif
+
+#include "w32file.h"
+#include "w32file-internals.h"
+
+#include "w32file-unix-glob.h"
+#include "w32handle.h"
+#include "w32error.h"
+#include "utils/mono-io-portability.h"
+#include "utils/mono-logger-internals.h"
+#include "utils/mono-os-mutex.h"
+#include "utils/mono-threads.h"
+#include "utils/mono-threads-api.h"
+#include "utils/strenc.h"
+
+typedef struct {
+ guint64 device;
+ guint64 inode;
+ guint32 sharemode;
+ guint32 access;
+ guint32 handle_refs;
+ guint32 timestamp;
+} FileShare;
+
+/* Currently used for both FILE, CONSOLE and PIPE handle types.
+ * This may have to change in future. */
+typedef struct {
+ gchar *filename;
+ FileShare *share_info; /* Pointer into shared mem */
+ gint fd;
+ guint32 security_attributes;
+ guint32 fileaccess;
+ guint32 sharemode;
+ guint32 attrs;
+} MonoW32HandleFile;
+
+typedef struct {
+ gchar **namelist;
+ gchar *dir_part;
+ gint num;
+ gsize count;
+} MonoW32HandleFind;
+
+/*
+ * If SHM is disabled, this will point to a hash of FileShare structures, otherwise
+ * it will be NULL. We use this instead of _wapi_fileshare_layout to avoid allocating a
+ * 4MB array.
+ */
+static GHashTable *file_share_table;
+static mono_mutex_t file_share_mutex;
+
+static void
+time_t_to_filetime (time_t timeval, FILETIME *filetime)
+{
+ guint64 ticks;
+
+ ticks = ((guint64)timeval * 10000000) + 116444736000000000ULL;
+ filetime->dwLowDateTime = ticks & 0xFFFFFFFF;
+ filetime->dwHighDateTime = ticks >> 32;
+}
+
+static void
+file_share_release (FileShare *share_info)
+{
+ /* Prevent new entries racing with us */
+ mono_os_mutex_lock (&file_share_mutex);
+
+ g_assert (share_info->handle_refs > 0);
+ share_info->handle_refs -= 1;
+
+ if (share_info->handle_refs == 0)
+ g_hash_table_remove (file_share_table, share_info);
+
+ mono_os_mutex_unlock (&file_share_mutex);
+}
+
+static gint
+file_share_equal (gconstpointer ka, gconstpointer kb)
+{
+ const FileShare *s1 = (const FileShare *)ka;
+ const FileShare *s2 = (const FileShare *)kb;
+
+ return (s1->device == s2->device && s1->inode == s2->inode) ? 1 : 0;
+}
+
+static guint
+file_share_hash (gconstpointer data)
+{
+ const FileShare *s = (const FileShare *)data;
+
+ return s->inode;
+}
+
+static gboolean
+file_share_get (guint64 device, guint64 inode, guint32 new_sharemode, guint32 new_access,
+ guint32 *old_sharemode, guint32 *old_access, FileShare **share_info)
+{
+ FileShare *file_share;
+ gboolean exists = FALSE;
+
+ /* Prevent new entries racing with us */
+ mono_os_mutex_lock (&file_share_mutex);
+
+ FileShare tmp;
+
+ /*
+ * Instead of allocating a 4MB array, we use a hash table to keep track of this
+ * info. This is needed even if SHM is disabled, to track sharing inside
+ * the current process.
+ */
+ if (!file_share_table)
+ file_share_table = g_hash_table_new_full (file_share_hash, file_share_equal, NULL, g_free);
+
+ tmp.device = device;
+ tmp.inode = inode;
+
+ file_share = (FileShare *)g_hash_table_lookup (file_share_table, &tmp);
+ if (file_share) {
+ *old_sharemode = file_share->sharemode;
+ *old_access = file_share->access;
+ *share_info = file_share;
+
+ g_assert (file_share->handle_refs > 0);
+ file_share->handle_refs += 1;
+
+ exists = TRUE;
+ } else {
+ file_share = g_new0 (FileShare, 1);
+
+ file_share->device = device;
+ file_share->inode = inode;
+ file_share->sharemode = new_sharemode;
+ file_share->access = new_access;
+ file_share->handle_refs = 1;
+ *share_info = file_share;
+
+ g_hash_table_insert (file_share_table, file_share, file_share);
+ }
+
+ mono_os_mutex_unlock (&file_share_mutex);
+
+ return(exists);
+}
+
+static gint
+_wapi_open (const gchar *pathname, gint flags, mode_t mode)
+{
+ gint fd;
+ gchar *located_filename;
+
+ if (flags & O_CREAT) {
+ located_filename = mono_portability_find_file (pathname, FALSE);
+ if (located_filename == NULL) {
+ fd = open (pathname, flags, mode);
+ } else {
+ fd = open (located_filename, flags, mode);
+ g_free (located_filename);
+ }
+ } else {
+ fd = open (pathname, flags, mode);
+ if (fd == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ located_filename = mono_portability_find_file (pathname, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ fd = open (located_filename, flags, mode);
+ g_free (located_filename);
+ }
+ }
+
+ return(fd);
+}
+
+static gint
+_wapi_access (const gchar *pathname, gint mode)
+{
+ gint ret;
+
+ ret = access (pathname, mode);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = access (located_filename, mode);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_chmod (const gchar *pathname, mode_t mode)
+{
+ gint ret;
+
+ ret = chmod (pathname, mode);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = chmod (located_filename, mode);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_utime (const gchar *filename, const struct utimbuf *buf)
+{
+ gint ret;
+
+ ret = utime (filename, buf);
+ if (ret == -1 && errno == ENOENT && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (filename, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = utime (located_filename, buf);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_unlink (const gchar *pathname)
+{
+ gint ret;
+
+ ret = unlink (pathname);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == EISDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = unlink (located_filename);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_rename (const gchar *oldpath, const gchar *newpath)
+{
+ gint ret;
+ gchar *located_newpath = mono_portability_find_file (newpath, FALSE);
+
+ if (located_newpath == NULL) {
+ ret = rename (oldpath, newpath);
+ } else {
+ ret = rename (oldpath, located_newpath);
+
+ if (ret == -1 && (errno == EISDIR || errno == ENAMETOOLONG || errno == ENOENT || errno == ENOTDIR || errno == EXDEV) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_oldpath = mono_portability_find_file (oldpath, TRUE);
+
+ if (located_oldpath == NULL) {
+ g_free (located_oldpath);
+ g_free (located_newpath);
+
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = rename (located_oldpath, located_newpath);
+ g_free (located_oldpath);
+ }
+ g_free (located_newpath);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_stat (const gchar *path, struct stat *buf)
+{
+ gint ret;
+
+ ret = stat (path, buf);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (path, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = stat (located_filename, buf);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_lstat (const gchar *path, struct stat *buf)
+{
+ gint ret;
+
+ ret = lstat (path, buf);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (path, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = lstat (located_filename, buf);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_mkdir (const gchar *pathname, mode_t mode)
+{
+ gint ret;
+ gchar *located_filename = mono_portability_find_file (pathname, FALSE);
+
+ if (located_filename == NULL) {
+ ret = mkdir (pathname, mode);
+ } else {
+ ret = mkdir (located_filename, mode);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_rmdir (const gchar *pathname)
+{
+ gint ret;
+
+ ret = rmdir (pathname);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (pathname, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = rmdir (located_filename);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gint
+_wapi_chdir (const gchar *path)
+{
+ gint ret;
+
+ ret = chdir (path);
+ if (ret == -1 && (errno == ENOENT || errno == ENOTDIR || errno == ENAMETOOLONG) && IS_PORTABILITY_SET) {
+ gint saved_errno = errno;
+ gchar *located_filename = mono_portability_find_file (path, TRUE);
+
+ if (located_filename == NULL) {
+ errno = saved_errno;
+ return -1;
+ }
+
+ ret = chdir (located_filename);
+ g_free (located_filename);
+ }
+
+ return ret;
+}
+
+static gchar*
+_wapi_basename (const gchar *filename)
+{
+ gchar *new_filename = g_strdup (filename), *ret;
+
+ if (IS_PORTABILITY_SET) {
+ g_strdelimit (new_filename, "\\", '/');
+ }
+
+ if (IS_PORTABILITY_DRIVE && g_ascii_isalpha (new_filename[0]) && (new_filename[1] == ':')) {
+ gint len = strlen (new_filename);
+
+ g_memmove (new_filename, new_filename + 2, len - 2);
+ new_filename[len - 2] = '\0';
+ }
+
+ ret = g_path_get_basename (new_filename);
+ g_free (new_filename);
+
+ return ret;
+}
+
+static gchar*
+_wapi_dirname (const gchar *filename)
+{
+ gchar *new_filename = g_strdup (filename), *ret;
+
+ if (IS_PORTABILITY_SET) {
+ g_strdelimit (new_filename, "\\", '/');
+ }
+
+ if (IS_PORTABILITY_DRIVE && g_ascii_isalpha (new_filename[0]) && (new_filename[1] == ':')) {
+ gint len = strlen (new_filename);
+
+ g_memmove (new_filename, new_filename + 2, len - 2);
+ new_filename[len - 2] = '\0';
+ }
+
+ ret = g_path_get_dirname (new_filename);
+ g_free (new_filename);
+
+ return ret;
+}
+
+static GDir*
+_wapi_g_dir_open (const gchar *path, guint flags, GError **error)
+{
+ GDir *ret;
+
+ ret = g_dir_open (path, flags, error);
+ if (ret == NULL && ((*error)->code == G_FILE_ERROR_NOENT || (*error)->code == G_FILE_ERROR_NOTDIR || (*error)->code == G_FILE_ERROR_NAMETOOLONG) && IS_PORTABILITY_SET) {
+ gchar *located_filename = mono_portability_find_file (path, TRUE);
+ GError *tmp_error = NULL;
+
+ if (located_filename == NULL) {
+ return(NULL);
+ }
+
+ ret = g_dir_open (located_filename, flags, &tmp_error);
+ g_free (located_filename);
+ if (tmp_error == NULL) {
+ g_clear_error (error);
+ }
+ }
+
+ return ret;
+}
+
+static gint
+get_errno_from_g_file_error (gint error)
+{
+ switch (error) {
+#ifdef EACCESS
+ case G_FILE_ERROR_ACCES: return EACCES;
+#endif
+#ifdef ENAMETOOLONG
+ case G_FILE_ERROR_NAMETOOLONG: return ENAMETOOLONG;
+#endif
+#ifdef ENOENT
+ case G_FILE_ERROR_NOENT: return ENOENT;
+#endif
+#ifdef ENOTDIR
+ case G_FILE_ERROR_NOTDIR: return ENOTDIR;
+#endif
+#ifdef ENXIO
+ case G_FILE_ERROR_NXIO: return ENXIO;
+#endif
+#ifdef ENODEV
+ case G_FILE_ERROR_NODEV: return ENODEV;
+#endif
+#ifdef EROFS
+ case G_FILE_ERROR_ROFS: return EROFS;
+#endif
+#ifdef ETXTBSY
+ case G_FILE_ERROR_TXTBSY: return ETXTBSY;
+#endif
+#ifdef EFAULT
+ case G_FILE_ERROR_FAULT: return EFAULT;
+#endif
+#ifdef ELOOP
+ case G_FILE_ERROR_LOOP: return ELOOP;
+#endif
+#ifdef ENOSPC
+ case G_FILE_ERROR_NOSPC: return ENOSPC;
+#endif
+#ifdef ENOMEM
+ case G_FILE_ERROR_NOMEM: return ENOMEM;
+#endif
+#ifdef EMFILE
+ case G_FILE_ERROR_MFILE: return EMFILE;
+#endif
+#ifdef ENFILE
+ case G_FILE_ERROR_NFILE: return ENFILE;
+#endif
+#ifdef EBADF
+ case G_FILE_ERROR_BADF: return EBADF;
+#endif
+#ifdef EINVAL
+ case G_FILE_ERROR_INVAL: return EINVAL;
+#endif
+#ifdef EPIPE
+ case G_FILE_ERROR_PIPE: return EPIPE;
+#endif
+#ifdef EAGAIN
+ case G_FILE_ERROR_AGAIN: return EAGAIN;
+#endif
+#ifdef EINTR
+ case G_FILE_ERROR_INTR: return EINTR;
+#endif
+#ifdef EWIO
+ case G_FILE_ERROR_IO: return EIO;
+#endif
+#ifdef EPERM
+ case G_FILE_ERROR_PERM: return EPERM;
+#endif
+ case G_FILE_ERROR_FAILED: return ERROR_INVALID_PARAMETER;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static gint
+file_compare (gconstpointer a, gconstpointer b)
+{
+ gchar *astr = *(gchar **) a;
+ gchar *bstr = *(gchar **) b;
+
+ return strcmp (astr, bstr);
+}
+
+/* scandir using glib */
+static gint
+_wapi_io_scandir (const gchar *dirname, const gchar *pattern, gchar ***namelist)
+{
+ GError *error = NULL;
+ GDir *dir;
+ GPtrArray *names;
+ gint result;
+ mono_w32file_unix_glob_t glob_buf;
+ gint flags = 0, i;
+
+ dir = _wapi_g_dir_open (dirname, 0, &error);
+ if (dir == NULL) {
+ /* g_dir_open returns ENOENT on directories on which we don't
+ * have read/x permission */
+ gint errnum = get_errno_from_g_file_error (error->code);
+ g_error_free (error);
+ if (errnum == ENOENT &&
+ !_wapi_access (dirname, F_OK) &&
+ _wapi_access (dirname, R_OK|X_OK)) {
+ errnum = EACCES;
+ }
+
+ errno = errnum;
+ return -1;
+ }
+
+ if (IS_PORTABILITY_CASE) {
+ flags = W32FILE_UNIX_GLOB_IGNORECASE;
+ }
+
+ result = mono_w32file_unix_glob (dir, pattern, flags, &glob_buf);
+ if (g_str_has_suffix (pattern, ".*")) {
+ /* Special-case the patterns ending in '.*', as
+ * windows also matches entries with no extension with
+ * this pattern.
+ *
+ * TODO: should this be a MONO_IOMAP option?
+ */
+ gchar *pattern2 = g_strndup (pattern, strlen (pattern) - 2);
+ gint result2;
+
+ g_dir_rewind (dir);
+ result2 = mono_w32file_unix_glob (dir, pattern2, flags | W32FILE_UNIX_GLOB_APPEND | W32FILE_UNIX_GLOB_UNIQUE, &glob_buf);
+
+ g_free (pattern2);
+
+ if (result != 0) {
+ result = result2;
+ }
+ }
+
+ g_dir_close (dir);
+ if (glob_buf.gl_pathc == 0) {
+ return(0);
+ } else if (result != 0) {
+ return -1;
+ }
+
+ names = g_ptr_array_new ();
+ for (i = 0; i < glob_buf.gl_pathc; i++) {
+ g_ptr_array_add (names, g_strdup (glob_buf.gl_pathv[i]));
+ }
+
+ mono_w32file_unix_globfree (&glob_buf);
+
+ result = names->len;
+ if (result > 0) {
+ g_ptr_array_sort (names, file_compare);
+ g_ptr_array_set_size (names, result + 1);
+
+ *namelist = (gchar **) g_ptr_array_free (names, FALSE);
+ } else {
+ g_ptr_array_free (names, TRUE);
+ }
+
+ return result;
+}
+
+static gboolean
+_wapi_lock_file_region (gint fd, off_t offset, off_t length)
+{
+#if defined(__native_client__)
+ printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
+ // behave as below -- locks are not available
+ return TRUE;
+#else
+ struct flock lock_data;
+ gint ret;
+
+ if (offset < 0 || length < 0) {
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ lock_data.l_type = F_WRLCK;
+ lock_data.l_whence = SEEK_SET;
+ lock_data.l_start = offset;
+ lock_data.l_len = length;
+
+ do {
+ ret = fcntl (fd, F_SETLK, &lock_data);
+ } while(ret == -1 && errno == EINTR);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
+
+ if (ret == -1) {
+ /*
+ * if locks are not available (NFS for example),
+ * ignore the error
+ */
+ if (errno == ENOLCK
+#ifdef EOPNOTSUPP
+ || errno == EOPNOTSUPP
+#endif
+#ifdef ENOTSUP
+ || errno == ENOTSUP
+#endif
+ ) {
+ return TRUE;
+ }
+
+ mono_w32error_set_last (ERROR_LOCK_VIOLATION);
+ return FALSE;
+ }
+
+ return TRUE;
+#endif /* __native_client__ */
+}
+
+static gboolean
+_wapi_unlock_file_region (gint fd, off_t offset, off_t length)
+{
+#if defined(__native_client__)
+ printf("WARNING: %s: fcntl() not available on Native Client!\n", __func__);
+ return TRUE;
+#else
+ struct flock lock_data;
+ gint ret;
+
+ lock_data.l_type = F_UNLCK;
+ lock_data.l_whence = SEEK_SET;
+ lock_data.l_start = offset;
+ lock_data.l_len = length;
+
+ do {
+ ret = fcntl (fd, F_SETLK, &lock_data);
+ } while(ret == -1 && errno == EINTR);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl returns %d", __func__, ret);
+
+ if (ret == -1) {
+ /*
+ * if locks are not available (NFS for example),
+ * ignore the error
+ */
+ if (errno == ENOLCK
+#ifdef EOPNOTSUPP
+ || errno == EOPNOTSUPP
+#endif
+#ifdef ENOTSUP
+ || errno == ENOTSUP
+#endif
+ ) {
+ return TRUE;
+ }
+
+ mono_w32error_set_last (ERROR_LOCK_VIOLATION);
+ return FALSE;
+ }
+
+ return TRUE;
+#endif /* __native_client__ */
+}
+
+static void file_close (gpointer handle, gpointer data);
+static void file_details (gpointer data);
+static const gchar* file_typename (void);
+static gsize file_typesize (void);
+static gint file_getfiletype(void);
+static gboolean file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+static gboolean file_flush(gpointer handle);
+static guint32 file_seek(gpointer handle, gint32 movedistance,
+ gint32 *highmovedistance, gint method);
+static gboolean file_setendoffile(gpointer handle);
+static guint32 file_getfilesize(gpointer handle, guint32 *highsize);
+static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
+ FILETIME *access_time,
+ FILETIME *write_time);
+static gboolean file_setfiletime(gpointer handle,
+ const FILETIME *create_time,
+ const FILETIME *access_time,
+ const FILETIME *write_time);
+static guint32 GetDriveTypeFromPath (const gchar *utf8_root_path_name);
+
+/* File handle is only signalled for overlapped IO */
+static MonoW32HandleOps _wapi_file_ops = {
+ file_close, /* close */
+ NULL, /* signal */
+ NULL, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ file_details, /* details */
+ file_typename, /* typename */
+ file_typesize, /* typesize */
+};
+
+static void console_close (gpointer handle, gpointer data);
+static void console_details (gpointer data);
+static const gchar* console_typename (void);
+static gsize console_typesize (void);
+static gint console_getfiletype(void);
+static gboolean console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+/* Console is mostly the same as file, except it can block waiting for
+ * input or output
+ */
+static MonoW32HandleOps _wapi_console_ops = {
+ console_close, /* close */
+ NULL, /* signal */
+ NULL, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ console_details, /* details */
+ console_typename, /* typename */
+ console_typesize, /* typesize */
+};
+
+static const gchar* find_typename (void);
+static gsize find_typesize (void);
+
+static MonoW32HandleOps _wapi_find_ops = {
+ NULL, /* close */
+ NULL, /* signal */
+ NULL, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ NULL, /* details */
+ find_typename, /* typename */
+ find_typesize, /* typesize */
+};
+
+static void pipe_close (gpointer handle, gpointer data);
+static void pipe_details (gpointer data);
+static const gchar* pipe_typename (void);
+static gsize pipe_typesize (void);
+static gint pipe_getfiletype (void);
+static gboolean pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+static gboolean pipe_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+/* Pipe handles
+ */
+static MonoW32HandleOps _wapi_pipe_ops = {
+ pipe_close, /* close */
+ NULL, /* signal */
+ NULL, /* own */
+ NULL, /* is_owned */
+ NULL, /* special_wait */
+ NULL, /* prewait */
+ pipe_details, /* details */
+ pipe_typename, /* typename */
+ pipe_typesize, /* typesize */
+};
+
+static const struct {
+ /* File, console and pipe handles */
+ gint (*getfiletype)(void);
+
+ /* File, console and pipe handles */
+ gboolean (*readfile)(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+ gboolean (*writefile)(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+ gboolean (*flushfile)(gpointer handle);
+
+ /* File handles */
+ guint32 (*seek)(gpointer handle, gint32 movedistance,
+ gint32 *highmovedistance, gint method);
+ gboolean (*setendoffile)(gpointer handle);
+ guint32 (*getfilesize)(gpointer handle, guint32 *highsize);
+ gboolean (*getfiletime)(gpointer handle, FILETIME *create_time,
+ FILETIME *access_time,
+ FILETIME *write_time);
+ gboolean (*setfiletime)(gpointer handle,
+ const FILETIME *create_time,
+ const FILETIME *access_time,
+ const FILETIME *write_time);
+} io_ops[MONO_W32HANDLE_COUNT]={
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* file */
+ {file_getfiletype,
+ file_read, file_write,
+ file_flush, file_seek,
+ file_setendoffile,
+ file_getfilesize,
+ file_getfiletime,
+ file_setfiletime},
+ /* console */
+ {console_getfiletype,
+ console_read,
+ console_write,
+ NULL, NULL, NULL, NULL, NULL, NULL},
+ /* thread */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* sem */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* mutex */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* event */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* socket (will need at least read and write) */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* find */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* process */
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* pipe */
+ {pipe_getfiletype,
+ pipe_read,
+ pipe_write,
+ NULL, NULL, NULL, NULL, NULL, NULL},
+};
+
+static gboolean lock_while_writing = FALSE;
+
+/* Some utility functions.
+ */
+
+/*
+ * Check if a file is writable by the current user.
+ *
+ * This is is a best effort kind of thing. It assumes a reasonable sane set
+ * of permissions by the underlying OS.
+ *
+ * We generally assume that basic unix permission bits are authoritative. Which might not
+ * be the case under systems with extended permissions systems (posix ACLs, SELinux, OSX/iOS sandboxing, etc)
+ *
+ * The choice of access as the fallback is due to the expected lower overhead compared to trying to open the file.
+ *
+ * The only expected problem with using access are for root, setuid or setgid programs as access is not consistent
+ * under those situations. It's to be expected that this should not happen in practice as those bits are very dangerous
+ * and should not be used with a dynamic runtime.
+ */
+static gboolean
+is_file_writable (struct stat *st, const gchar *path)
+{
+#if __APPLE__
+ // OS X Finder "locked" or `ls -lO` "uchg".
+ // This only covers one of several cases where an OS X file could be unwritable through special flags.
+ if (st->st_flags & (UF_IMMUTABLE|SF_IMMUTABLE))
+ return 0;
+#endif
+
+ /* Is it globally writable? */
+ if (st->st_mode & S_IWOTH)
+ return 1;
+
+ /* Am I the owner? */
+ if ((st->st_uid == geteuid ()) && (st->st_mode & S_IWUSR))
+ return 1;
+
+ /* Am I in the same group? */
+ if ((st->st_gid == getegid ()) && (st->st_mode & S_IWGRP))
+ return 1;
+
+ /* Fallback to using access(2). It's not ideal as it might not take into consideration euid/egid
+ * but it's the only sane option we have on unix.
+ */
+ return access (path, W_OK) == 0;
+}
+
+
+static guint32 _wapi_stat_to_file_attributes (const gchar *pathname,
+ struct stat *buf,
+ struct stat *lbuf)
+{
+ guint32 attrs = 0;
+ gchar *filename;
+
+ /* FIXME: this could definitely be better, but there seems to
+ * be no pattern to the attributes that are set
+ */
+
+ /* Sockets (0140000) != Directory (040000) + Regular file (0100000) */
+ if (S_ISSOCK (buf->st_mode))
+ buf->st_mode &= ~S_IFSOCK; /* don't consider socket protection */
+
+ filename = _wapi_basename (pathname);
+
+ if (S_ISDIR (buf->st_mode)) {
+ attrs = FILE_ATTRIBUTE_DIRECTORY;
+ if (!is_file_writable (buf, pathname)) {
+ attrs |= FILE_ATTRIBUTE_READONLY;
+ }
+ if (filename[0] == '.') {
+ attrs |= FILE_ATTRIBUTE_HIDDEN;
+ }
+ } else {
+ if (!is_file_writable (buf, pathname)) {
+ attrs = FILE_ATTRIBUTE_READONLY;
+
+ if (filename[0] == '.') {
+ attrs |= FILE_ATTRIBUTE_HIDDEN;
+ }
+ } else if (filename[0] == '.') {
+ attrs = FILE_ATTRIBUTE_HIDDEN;
+ } else {
+ attrs = FILE_ATTRIBUTE_NORMAL;
+ }
+ }
+
+ if (lbuf != NULL) {
+ if (S_ISLNK (lbuf->st_mode)) {
+ attrs |= FILE_ATTRIBUTE_REPARSE_POINT;
+ }
+ }
+
+ g_free (filename);
+
+ return attrs;
+}
+
+static void
+_wapi_set_last_error_from_errno (void)
+{
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
+}
+
+static void _wapi_set_last_path_error_from_errno (const gchar *dir,
+ const gchar *path)
+{
+ if (errno == ENOENT) {
+ /* Check the path - if it's a missing directory then
+ * we need to set PATH_NOT_FOUND not FILE_NOT_FOUND
+ */
+ gchar *dirname;
+
+
+ if (dir == NULL) {
+ dirname = _wapi_dirname (path);
+ } else {
+ dirname = g_strdup (dir);
+ }
+
+ if (_wapi_access (dirname, F_OK) == 0) {
+ mono_w32error_set_last (ERROR_FILE_NOT_FOUND);
+ } else {
+ mono_w32error_set_last (ERROR_PATH_NOT_FOUND);
+ }
+
+ g_free (dirname);
+ } else {
+ _wapi_set_last_error_from_errno ();
+ }
+}
+
+/* Handle ops.
+ */
+static void file_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleFile *file_handle = (MonoW32HandleFile *)data;
+ gint fd = file_handle->fd;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing file handle %p [%s]", __func__, handle,
+ file_handle->filename);
+
+ if (file_handle->attrs & FILE_FLAG_DELETE_ON_CLOSE)
+ _wapi_unlink (file_handle->filename);
+
+ g_free (file_handle->filename);
+
+ if (file_handle->share_info)
+ file_share_release (file_handle->share_info);
+
+ close (fd);
+}
+
+static void file_details (gpointer data)
+{
+ MonoW32HandleFile *file = (MonoW32HandleFile *)data;
+
+ g_print ("[%20s] acc: %c%c%c, shr: %c%c%c, attrs: %5u",
+ file->filename,
+ file->fileaccess&GENERIC_READ?'R':'.',
+ file->fileaccess&GENERIC_WRITE?'W':'.',
+ file->fileaccess&GENERIC_EXECUTE?'X':'.',
+ file->sharemode&FILE_SHARE_READ?'R':'.',
+ file->sharemode&FILE_SHARE_WRITE?'W':'.',
+ file->sharemode&FILE_SHARE_DELETE?'D':'.',
+ file->attrs);
+}
+
+static const gchar* file_typename (void)
+{
+ return "File";
+}
+
+static gsize file_typesize (void)
+{
+ return sizeof (MonoW32HandleFile);
+}
+
+static gint file_getfiletype(void)
+{
+ return(FILE_TYPE_DISK);
+}
+
+static gboolean
+file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ gint fd, ret;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ fd = file_handle->fd;
+ if(bytesread!=NULL) {
+ *bytesread=0;
+ }
+
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ do {
+ ret = read (fd, buffer, numbytes);
+ } while (ret == -1 && errno == EINTR &&
+ !mono_thread_info_is_interrupt_state (info));
+
+ if(ret==-1) {
+ gint err = errno;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
+ handle, strerror(err));
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (err));
+ return(FALSE);
+ }
+
+ if (bytesread != NULL) {
+ *bytesread = ret;
+ }
+
+ return(TRUE);
+}
+
+static gboolean
+file_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ gint ret, fd;
+ off_t current_pos = 0;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ fd = file_handle->fd;
+
+ if(byteswritten!=NULL) {
+ *byteswritten=0;
+ }
+
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ if (lock_while_writing) {
+ /* Need to lock the region we're about to write to,
+ * because we only do advisory locking on POSIX
+ * systems
+ */
+ current_pos = lseek (fd, (off_t)0, SEEK_CUR);
+ if (current_pos == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
+ handle, strerror (errno));
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ if (_wapi_lock_file_region (fd, current_pos,
+ numbytes) == FALSE) {
+ /* The error has already been set */
+ return(FALSE);
+ }
+ }
+
+ do {
+ ret = write (fd, buffer, numbytes);
+ } while (ret == -1 && errno == EINTR &&
+ !mono_thread_info_is_interrupt_state (info));
+
+ if (lock_while_writing) {
+ _wapi_unlock_file_region (fd, current_pos, numbytes);
+ }
+
+ if (ret == -1) {
+ if (errno == EINTR) {
+ ret = 0;
+ } else {
+ _wapi_set_last_error_from_errno ();
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
+ __func__, handle, strerror(errno));
+
+ return(FALSE);
+ }
+ }
+ if (byteswritten != NULL) {
+ *byteswritten = ret;
+ }
+ return(TRUE);
+}
+
+static gboolean file_flush(gpointer handle)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ gint ret, fd;
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ fd = file_handle->fd;
+
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ ret=fsync(fd);
+ if (ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fsync of handle %p error: %s", __func__, handle,
+ strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+static guint32 file_seek(gpointer handle, gint32 movedistance,
+ gint32 *highmovedistance, gint method)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ gint64 offset, newpos;
+ gint whence, fd;
+ guint32 ret;
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(INVALID_SET_FILE_POINTER);
+ }
+
+ fd = file_handle->fd;
+
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(INVALID_SET_FILE_POINTER);
+ }
+
+ switch(method) {
+ case FILE_BEGIN:
+ whence=SEEK_SET;
+ break;
+ case FILE_CURRENT:
+ whence=SEEK_CUR;
+ break;
+ case FILE_END:
+ whence=SEEK_END;
+ break;
+ default:
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: invalid seek type %d", __func__, method);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(INVALID_SET_FILE_POINTER);
+ }
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+ if(highmovedistance==NULL) {
+ offset=movedistance;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld (low %d)", __func__,
+ offset, movedistance);
+ } else {
+ offset=((gint64) *highmovedistance << 32) | (guint32)movedistance;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting offset to %lld 0x%llx (high %d 0x%x, low %d 0x%x)", __func__, offset, offset, *highmovedistance, *highmovedistance, movedistance, movedistance);
+ }
+#else
+ offset=movedistance;
+#endif
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: moving handle %p by %lld bytes from %d", __func__,
+ handle, (long long)offset, whence);
+
+#ifdef PLATFORM_ANDROID
+ /* bionic doesn't support -D_FILE_OFFSET_BITS=64 */
+ newpos=lseek64(fd, offset, whence);
+#else
+ newpos=lseek(fd, offset, whence);
+#endif
+ if(newpos==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek on handle %p returned error %s",
+ __func__, handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(INVALID_SET_FILE_POINTER);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lseek returns %lld", __func__, newpos);
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+ ret=newpos & 0xFFFFFFFF;
+ if(highmovedistance!=NULL) {
+ *highmovedistance=newpos>>32;
+ }
+#else
+ ret=newpos;
+ if(highmovedistance!=NULL) {
+ /* Accurate, but potentially dodgy :-) */
+ *highmovedistance=0;
+ }
+#endif
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: move of handle %p returning %d/%d", __func__,
+ handle, ret, highmovedistance==NULL?0:*highmovedistance);
+
+ return(ret);
+}
+
+static gboolean file_setendoffile(gpointer handle)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ struct stat statbuf;
+ off_t pos;
+ gint ret, fd;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = file_handle->fd;
+
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ /* Find the current file position, and the file length. If
+ * the file position is greater than the length, write to
+ * extend the file with a hole. If the file position is less
+ * than the length, truncate the file.
+ */
+
+ ret=fstat(fd, &statbuf);
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
+ handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ pos=lseek(fd, (off_t)0, SEEK_CUR);
+ if(pos==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p lseek failed: %s", __func__,
+ handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+#ifdef FTRUNCATE_DOESNT_EXTEND
+ off_t size = statbuf.st_size;
+ /* I haven't bothered to write the configure.ac stuff for this
+ * because I don't know if any platform needs it. I'm leaving
+ * this code just in case though
+ */
+ if(pos>size) {
+ /* Extend the file. Use write() here, because some
+ * manuals say that ftruncate() behaviour is undefined
+ * when the file needs extending. The POSIX spec says
+ * that on XSI-conformant systems it extends, so if
+ * every system we care about conforms, then we can
+ * drop this write.
+ */
+ do {
+ ret = write (fd, "", 1);
+ } while (ret == -1 && errno == EINTR &&
+ !mono_thread_info_is_interrupt_state (info));
+
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p extend write failed: %s", __func__, handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ /* And put the file position back after the write */
+ ret = lseek (fd, pos, SEEK_SET);
+ if (ret == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p second lseek failed: %s",
+ __func__, handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+ }
+#endif
+
+/* Native Client has no ftruncate function, even in standalone sel_ldr. */
+#ifndef __native_client__
+ /* always truncate, because the extend write() adds an extra
+ * byte to the end of the file
+ */
+ do {
+ ret=ftruncate(fd, pos);
+ }
+ while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ftruncate failed: %s", __func__,
+ handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+#endif
+
+ return(TRUE);
+}
+
+static guint32 file_getfilesize(gpointer handle, guint32 *highsize)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ struct stat statbuf;
+ guint32 size;
+ gint ret;
+ gint fd;
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(INVALID_FILE_SIZE);
+ }
+ fd = file_handle->fd;
+
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(INVALID_FILE_SIZE);
+ }
+
+ /* If the file has a size with the low bits 0xFFFFFFFF the
+ * caller can't tell if this is an error, so clear the error
+ * value
+ */
+ mono_w32error_set_last (ERROR_SUCCESS);
+
+ ret = fstat(fd, &statbuf);
+ if (ret == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__,
+ handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(INVALID_FILE_SIZE);
+ }
+
+ /* fstat indicates block devices as zero-length, so go a different path */
+#ifdef BLKGETSIZE64
+ if (S_ISBLK(statbuf.st_mode)) {
+ guint64 bigsize;
+ if (ioctl(fd, BLKGETSIZE64, &bigsize) < 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p ioctl BLKGETSIZE64 failed: %s",
+ __func__, handle, strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(INVALID_FILE_SIZE);
+ }
+
+ size = bigsize & 0xFFFFFFFF;
+ if (highsize != NULL) {
+ *highsize = bigsize>>32;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning block device size %d/%d",
+ __func__, size, *highsize);
+
+ return(size);
+ }
+#endif
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+ size = statbuf.st_size & 0xFFFFFFFF;
+ if (highsize != NULL) {
+ *highsize = statbuf.st_size>>32;
+ }
+#else
+ if (highsize != NULL) {
+ /* Accurate, but potentially dodgy :-) */
+ *highsize = 0;
+ }
+ size = statbuf.st_size;
+#endif
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning size %d/%d", __func__, size, *highsize);
+
+ return(size);
+}
+
+static gboolean file_getfiletime(gpointer handle, FILETIME *create_time,
+ FILETIME *access_time,
+ FILETIME *write_time)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ struct stat statbuf;
+ guint64 create_ticks, access_ticks, write_ticks;
+ gint ret, fd;
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = file_handle->fd;
+
+ if(!(file_handle->fileaccess & GENERIC_READ) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ ret=fstat(fd, &statbuf);
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
+ strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: atime: %ld ctime: %ld mtime: %ld", __func__,
+ statbuf.st_atime, statbuf.st_ctime,
+ statbuf.st_mtime);
+
+ /* Try and guess a meaningful create time by using the older
+ * of atime or ctime
+ */
+ /* The magic constant comes from msdn documentation
+ * "Converting a time_t Value to a File Time"
+ */
+ if(statbuf.st_atime < statbuf.st_ctime) {
+ create_ticks=((guint64)statbuf.st_atime*10000000)
+ + 116444736000000000ULL;
+ } else {
+ create_ticks=((guint64)statbuf.st_ctime*10000000)
+ + 116444736000000000ULL;
+ }
+
+ access_ticks=((guint64)statbuf.st_atime*10000000)+116444736000000000ULL;
+ write_ticks=((guint64)statbuf.st_mtime*10000000)+116444736000000000ULL;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: aticks: %llu cticks: %llu wticks: %llu", __func__,
+ access_ticks, create_ticks, write_ticks);
+
+ if(create_time!=NULL) {
+ create_time->dwLowDateTime = create_ticks & 0xFFFFFFFF;
+ create_time->dwHighDateTime = create_ticks >> 32;
+ }
+
+ if(access_time!=NULL) {
+ access_time->dwLowDateTime = access_ticks & 0xFFFFFFFF;
+ access_time->dwHighDateTime = access_ticks >> 32;
+ }
+
+ if(write_time!=NULL) {
+ write_time->dwLowDateTime = write_ticks & 0xFFFFFFFF;
+ write_time->dwHighDateTime = write_ticks >> 32;
+ }
+
+ return(TRUE);
+}
+
+static gboolean file_setfiletime(gpointer handle,
+ const FILETIME *create_time G_GNUC_UNUSED,
+ const FILETIME *access_time,
+ const FILETIME *write_time)
+{
+ MonoW32HandleFile *file_handle;
+ gboolean ok;
+ struct utimbuf utbuf;
+ struct stat statbuf;
+ guint64 access_ticks, write_ticks;
+ gint ret, fd;
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE,
+ (gpointer *)&file_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up file handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = file_handle->fd;
+
+ if(!(file_handle->fileaccess & GENERIC_WRITE) &&
+ !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ if(file_handle->filename == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p unknown filename", __func__, handle);
+
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ /* Get the current times, so we can put the same times back in
+ * the event that one of the FileTime structs is NULL
+ */
+ ret=fstat (fd, &statbuf);
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p fstat failed: %s", __func__, handle,
+ strerror(errno));
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ if(access_time!=NULL) {
+ access_ticks=((guint64)access_time->dwHighDateTime << 32) +
+ access_time->dwLowDateTime;
+ /* This is (time_t)0. We can actually go to INT_MIN,
+ * but this will do for now.
+ */
+ if (access_ticks < 116444736000000000ULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set access time too early",
+ __func__);
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ if (sizeof (utbuf.actime) == 4 && ((access_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
+ __func__);
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ utbuf.actime=(access_ticks - 116444736000000000ULL) / 10000000;
+ } else {
+ utbuf.actime=statbuf.st_atime;
+ }
+
+ if(write_time!=NULL) {
+ write_ticks=((guint64)write_time->dwHighDateTime << 32) +
+ write_time->dwLowDateTime;
+ /* This is (time_t)0. We can actually go to INT_MIN,
+ * but this will do for now.
+ */
+ if (write_ticks < 116444736000000000ULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time too early",
+ __func__);
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+ if (sizeof (utbuf.modtime) == 4 && ((write_ticks - 116444736000000000ULL) / 10000000) > INT_MAX) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: attempt to set write time that is too big for a 32bits time_t",
+ __func__);
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ utbuf.modtime=(write_ticks - 116444736000000000ULL) / 10000000;
+ } else {
+ utbuf.modtime=statbuf.st_mtime;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: setting handle %p access %ld write %ld", __func__,
+ handle, utbuf.actime, utbuf.modtime);
+
+ ret = _wapi_utime (file_handle->filename, &utbuf);
+ if (ret == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p [%s] utime failed: %s", __func__,
+ handle, file_handle->filename, strerror(errno));
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+static void console_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleFile *console_handle = (MonoW32HandleFile *)data;
+ gint fd = console_handle->fd;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing console handle %p", __func__, handle);
+
+ g_free (console_handle->filename);
+
+ if (fd > 2) {
+ if (console_handle->share_info)
+ file_share_release (console_handle->share_info);
+ close (fd);
+ }
+}
+
+static void console_details (gpointer data)
+{
+ file_details (data);
+}
+
+static const gchar* console_typename (void)
+{
+ return "Console";
+}
+
+static gsize console_typesize (void)
+{
+ return sizeof (MonoW32HandleFile);
+}
+
+static gint console_getfiletype(void)
+{
+ return(FILE_TYPE_CHAR);
+}
+
+static gboolean
+console_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+ MonoW32HandleFile *console_handle;
+ gboolean ok;
+ gint ret, fd;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+ (gpointer *)&console_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up console handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = console_handle->fd;
+
+ if(bytesread!=NULL) {
+ *bytesread=0;
+ }
+
+ if(!(console_handle->fileaccess & GENERIC_READ) &&
+ !(console_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, console_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ do {
+ ret=read(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
+
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__, handle,
+ strerror(errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ if(bytesread!=NULL) {
+ *bytesread=ret;
+ }
+
+ return(TRUE);
+}
+
+static gboolean
+console_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+ MonoW32HandleFile *console_handle;
+ gboolean ok;
+ gint ret, fd;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+ (gpointer *)&console_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up console handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = console_handle->fd;
+
+ if(byteswritten!=NULL) {
+ *byteswritten=0;
+ }
+
+ if(!(console_handle->fileaccess & GENERIC_WRITE) &&
+ !(console_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, console_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ do {
+ ret = write(fd, buffer, numbytes);
+ } while (ret == -1 && errno == EINTR &&
+ !mono_thread_info_is_interrupt_state (info));
+
+ if (ret == -1) {
+ if (errno == EINTR) {
+ ret = 0;
+ } else {
+ _wapi_set_last_error_from_errno ();
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s",
+ __func__, handle, strerror(errno));
+
+ return(FALSE);
+ }
+ }
+ if(byteswritten!=NULL) {
+ *byteswritten=ret;
+ }
+
+ return(TRUE);
+}
+
+static const gchar* find_typename (void)
+{
+ return "Find";
+}
+
+static gsize find_typesize (void)
+{
+ return sizeof (MonoW32HandleFind);
+}
+
+static void pipe_close (gpointer handle, gpointer data)
+{
+ MonoW32HandleFile *pipe_handle = (MonoW32HandleFile*)data;
+ gint fd = pipe_handle->fd;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing pipe handle %p fd %d", __func__, handle, fd);
+
+ /* No filename with pipe handles */
+
+ if (pipe_handle->share_info)
+ file_share_release (pipe_handle->share_info);
+
+ close (fd);
+}
+
+static void pipe_details (gpointer data)
+{
+ file_details (data);
+}
+
+static const gchar* pipe_typename (void)
+{
+ return "Pipe";
+}
+
+static gsize pipe_typesize (void)
+{
+ return sizeof (MonoW32HandleFile);
+}
+
+static gint pipe_getfiletype(void)
+{
+ return(FILE_TYPE_PIPE);
+}
+
+static gboolean
+pipe_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+ MonoW32HandleFile *pipe_handle;
+ gboolean ok;
+ gint ret, fd;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
+ (gpointer *)&pipe_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up pipe handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = pipe_handle->fd;
+
+ if(bytesread!=NULL) {
+ *bytesread=0;
+ }
+
+ if(!(pipe_handle->fileaccess & GENERIC_READ) &&
+ !(pipe_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ access: %u",
+ __func__, handle, pipe_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: reading up to %d bytes from pipe %p", __func__,
+ numbytes, handle);
+
+ do {
+ ret=read(fd, buffer, numbytes);
+ } while (ret==-1 && errno==EINTR && !mono_thread_info_is_interrupt_state (info));
+
+ if (ret == -1) {
+ if (errno == EINTR) {
+ ret = 0;
+ } else {
+ _wapi_set_last_error_from_errno ();
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read of handle %p error: %s", __func__,
+ handle, strerror(errno));
+
+ return(FALSE);
+ }
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: read %d bytes from pipe %p", __func__, ret, handle);
+
+ if(bytesread!=NULL) {
+ *bytesread=ret;
+ }
+
+ return(TRUE);
+}
+
+static gboolean
+pipe_write(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+ MonoW32HandleFile *pipe_handle;
+ gboolean ok;
+ gint ret, fd;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_PIPE,
+ (gpointer *)&pipe_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up pipe handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+ fd = pipe_handle->fd;
+
+ if(byteswritten!=NULL) {
+ *byteswritten=0;
+ }
+
+ if(!(pipe_handle->fileaccess & GENERIC_WRITE) &&
+ !(pipe_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_WRITE access: %u", __func__, handle, pipe_handle->fileaccess);
+
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return(FALSE);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: writing up to %d bytes to pipe %p", __func__, numbytes,
+ handle);
+
+ do {
+ ret = write (fd, buffer, numbytes);
+ } while (ret == -1 && errno == EINTR &&
+ !mono_thread_info_is_interrupt_state (info));
+
+ if (ret == -1) {
+ if (errno == EINTR) {
+ ret = 0;
+ } else {
+ _wapi_set_last_error_from_errno ();
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write of handle %p error: %s", __func__,
+ handle, strerror(errno));
+
+ return(FALSE);
+ }
+ }
+ if(byteswritten!=NULL) {
+ *byteswritten=ret;
+ }
+
+ return(TRUE);
+}
+
+static gint convert_flags(guint32 fileaccess, guint32 createmode)
+{
+ gint flags=0;
+
+ switch(fileaccess) {
+ case GENERIC_READ:
+ flags=O_RDONLY;
+ break;
+ case GENERIC_WRITE:
+ flags=O_WRONLY;
+ break;
+ case GENERIC_READ|GENERIC_WRITE:
+ flags=O_RDWR;
+ break;
+ default:
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown access type 0x%x", __func__,
+ fileaccess);
+ break;
+ }
+
+ switch(createmode) {
+ case CREATE_NEW:
+ flags|=O_CREAT|O_EXCL;
+ break;
+ case CREATE_ALWAYS:
+ flags|=O_CREAT|O_TRUNC;
+ break;
+ case OPEN_EXISTING:
+ break;
+ case OPEN_ALWAYS:
+ flags|=O_CREAT;
+ break;
+ case TRUNCATE_EXISTING:
+ flags|=O_TRUNC;
+ break;
+ default:
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unknown create mode 0x%x", __func__,
+ createmode);
+ break;
+ }
+
+ return(flags);
+}
+
+#if 0 /* unused */
+static mode_t convert_perms(guint32 sharemode)
+{
+ mode_t perms=0600;
+
+ if(sharemode&FILE_SHARE_READ) {
+ perms|=044;
+ }
+ if(sharemode&FILE_SHARE_WRITE) {
+ perms|=022;
+ }
+
+ return(perms);
+}
+#endif
+
+static gboolean share_allows_open (struct stat *statbuf, guint32 sharemode,
+ guint32 fileaccess,
+ FileShare **share_info)
+{
+ gboolean file_already_shared;
+ guint32 file_existing_share, file_existing_access;
+
+ file_already_shared = file_share_get (statbuf->st_dev, statbuf->st_ino, sharemode, fileaccess, &file_existing_share, &file_existing_access, share_info);
+
+ if (file_already_shared) {
+ /* The reference to this share info was incremented
+ * when we looked it up, so be careful to put it back
+ * if we conclude we can't use this file.
+ */
+ if (file_existing_share == 0) {
+ /* Quick and easy, no possibility to share */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, fileaccess);
+
+ file_share_release (*share_info);
+
+ return(FALSE);
+ }
+
+ if (((file_existing_share == FILE_SHARE_READ) &&
+ (fileaccess != GENERIC_READ)) ||
+ ((file_existing_share == FILE_SHARE_WRITE) &&
+ (fileaccess != GENERIC_WRITE))) {
+ /* New access mode doesn't match up */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, fileaccess, file_existing_share);
+
+ file_share_release (*share_info);
+
+ return(FALSE);
+ }
+
+ if (((file_existing_access & GENERIC_READ) &&
+ !(sharemode & FILE_SHARE_READ)) ||
+ ((file_existing_access & GENERIC_WRITE) &&
+ !(sharemode & FILE_SHARE_WRITE))) {
+ /* New share mode doesn't match up */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Access mode prevents open: requested share: 0x%x, file has access: 0x%x", __func__, sharemode, file_existing_access);
+
+ file_share_release (*share_info);
+
+ return(FALSE);
+ }
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
+ }
+
+ return(TRUE);
+}
+
+
+static gboolean
+share_allows_delete (struct stat *statbuf, FileShare **share_info)
+{
+ gboolean file_already_shared;
+ guint32 file_existing_share, file_existing_access;
+
+ file_already_shared = file_share_get (statbuf->st_dev, statbuf->st_ino, FILE_SHARE_DELETE, GENERIC_READ, &file_existing_share, &file_existing_access, share_info);
+
+ if (file_already_shared) {
+ /* The reference to this share info was incremented
+ * when we looked it up, so be careful to put it back
+ * if we conclude we can't use this file.
+ */
+ if (file_existing_share == 0) {
+ /* Quick and easy, no possibility to share */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing = NONE", __func__, (*share_info)->access);
+
+ file_share_release (*share_info);
+
+ return(FALSE);
+ }
+
+ if (!(file_existing_share & FILE_SHARE_DELETE)) {
+ /* New access mode doesn't match up */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Share mode prevents open: requested access: 0x%x, file has sharing: 0x%x", __func__, (*share_info)->access, file_existing_share);
+
+ file_share_release (*share_info);
+
+ return(FALSE);
+ }
+ } else {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: New file!", __func__);
+ }
+
+ return(TRUE);
+}
+
+gpointer
+mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
+{
+ MonoW32HandleFile file_handle = {0};
+ gpointer handle;
+ gint flags=convert_flags(fileaccess, createmode);
+ /*mode_t perms=convert_perms(sharemode);*/
+ /* we don't use sharemode, because that relates to sharing of
+ * the file when the file is open and is already handled by
+ * other code, perms instead are the on-disk permissions and
+ * this is a sane default.
+ */
+ mode_t perms=0666;
+ gchar *filename;
+ gint fd, ret;
+ MonoW32HandleType handle_type;
+ struct stat statbuf;
+
+ if (attrs & FILE_ATTRIBUTE_TEMPORARY)
+ perms = 0600;
+
+ if (attrs & FILE_ATTRIBUTE_ENCRYPTED){
+ mono_w32error_set_last (ERROR_ENCRYPTION_FAILED);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ filename = mono_unicode_to_external (name);
+ if (filename == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Opening %s with share 0x%x and access 0x%x", __func__,
+ filename, sharemode, fileaccess);
+
+ fd = _wapi_open (filename, flags, perms);
+
+ /* If we were trying to open a directory with write permissions
+ * (e.g. O_WRONLY or O_RDWR), this call will fail with
+ * EISDIR. However, this is a bit bogus because calls to
+ * manipulate the directory (e.g. mono_w32file_set_times) will still work on
+ * the directory because they use other API calls
+ * (e.g. utime()). Hence, if we failed with the EISDIR error, try
+ * to open the directory again without write permission.
+ */
+ if (fd == -1 && errno == EISDIR)
+ {
+ /* Try again but don't try to make it writable */
+ fd = _wapi_open (filename, flags & ~(O_RDWR|O_WRONLY), perms);
+ }
+
+ if (fd == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename,
+ strerror(errno));
+ _wapi_set_last_path_error_from_errno (NULL, filename);
+ g_free (filename);
+
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ if (fd >= mono_w32handle_fd_reserve) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
+
+ mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
+
+ close (fd);
+ g_free (filename);
+
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ ret = fstat (fd, &statbuf);
+ if (ret == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fstat error of file %s: %s", __func__,
+ filename, strerror (errno));
+ _wapi_set_last_error_from_errno ();
+ g_free (filename);
+ close (fd);
+
+ return(INVALID_HANDLE_VALUE);
+ }
+#ifdef __native_client__
+ /* Workaround: Native Client currently returns the same fake inode
+ * for all files, so do a simple hash on the filename so we don't
+ * use the same share info for each file.
+ */
+ statbuf.st_ino = g_str_hash(filename);
+#endif
+
+ if (share_allows_open (&statbuf, sharemode, fileaccess,
+ &file_handle.share_info) == FALSE) {
+ mono_w32error_set_last (ERROR_SHARING_VIOLATION);
+ g_free (filename);
+ close (fd);
+
+ return (INVALID_HANDLE_VALUE);
+ }
+ if (file_handle.share_info == NULL) {
+ /* No space, so no more files can be opened */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No space in the share table", __func__);
+
+ mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
+ close (fd);
+ g_free (filename);
+
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ file_handle.filename = filename;
+
+ file_handle.fd = fd;
+ file_handle.fileaccess=fileaccess;
+ file_handle.sharemode=sharemode;
+ file_handle.attrs=attrs;
+
+#ifdef HAVE_POSIX_FADVISE
+ if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
+ posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ if (attrs & FILE_FLAG_RANDOM_ACCESS)
+ posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM);
+#endif
+
+#ifdef F_RDAHEAD
+ if (attrs & FILE_FLAG_SEQUENTIAL_SCAN)
+ fcntl(fd, F_RDAHEAD, 1);
+#endif
+
+#ifndef S_ISFIFO
+#define S_ISFIFO(m) ((m & S_IFIFO) != 0)
+#endif
+ if (S_ISFIFO (statbuf.st_mode)) {
+ handle_type = MONO_W32HANDLE_PIPE;
+ /* maintain invariant that pipes have no filename */
+ file_handle.filename = NULL;
+ g_free (filename);
+ filename = NULL;
+ } else if (S_ISCHR (statbuf.st_mode)) {
+ handle_type = MONO_W32HANDLE_CONSOLE;
+ } else {
+ handle_type = MONO_W32HANDLE_FILE;
+ }
+
+ handle = mono_w32handle_new_fd (handle_type, fd, &file_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating file handle", __func__);
+ g_free (filename);
+ close (fd);
+
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
+
+ return(handle);
+}
+
+gboolean
+mono_w32file_close (gpointer handle)
+{
+ return mono_w32handle_close (handle);
+}
+
+gboolean mono_w32file_delete(const gunichar2 *name)
+{
+ gchar *filename;
+ gint retval;
+ gboolean ret = FALSE;
+ guint32 attrs;
+#if 0
+ struct stat statbuf;
+ FileShare *shareinfo;
+#endif
+
+ if(name==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ filename=mono_unicode_to_external(name);
+ if(filename==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ attrs = mono_w32file_get_attributes (name);
+ if (attrs == INVALID_FILE_ATTRIBUTES) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
+ /* Error set by mono_w32file_get_attributes() */
+ g_free (filename);
+ return(FALSE);
+ }
+
+#if 0
+ /* Check to make sure sharing allows us to open the file for
+ * writing. See bug 323389.
+ *
+ * Do the checks that don't need an open file descriptor, for
+ * simplicity's sake. If we really have to do the full checks
+ * then we can implement that later.
+ */
+ if (_wapi_stat (filename, &statbuf) < 0) {
+ _wapi_set_last_path_error_from_errno (NULL, filename);
+ g_free (filename);
+ return(FALSE);
+ }
+
+ if (share_allows_open (&statbuf, 0, GENERIC_WRITE,
+ &shareinfo) == FALSE) {
+ mono_w32error_set_last (ERROR_SHARING_VIOLATION);
+ g_free (filename);
+ return FALSE;
+ }
+ if (shareinfo)
+ file_share_release (shareinfo);
+#endif
+
+ retval = _wapi_unlink (filename);
+
+ if (retval == -1) {
+ _wapi_set_last_path_error_from_errno (NULL, filename);
+ } else {
+ ret = TRUE;
+ }
+
+ g_free(filename);
+
+ return(ret);
+}
+
+static gboolean
+MoveFile (gunichar2 *name, gunichar2 *dest_name)
+{
+ gchar *utf8_name, *utf8_dest_name;
+ gint result, errno_copy;
+ struct stat stat_src, stat_dest;
+ gboolean ret = FALSE;
+ FileShare *shareinfo;
+
+ if(name==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_name = mono_unicode_to_external (name);
+ if (utf8_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return FALSE;
+ }
+
+ if(dest_name==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ g_free (utf8_name);
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_dest_name = mono_unicode_to_external (dest_name);
+ if (utf8_dest_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ g_free (utf8_name);
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return FALSE;
+ }
+
+ /*
+ * In C# land we check for the existence of src, but not for dest.
+ * We check it here and return the failure if dest exists and is not
+ * the same file as src.
+ */
+ if (_wapi_stat (utf8_name, &stat_src) < 0) {
+ if (errno != ENOENT || _wapi_lstat (utf8_name, &stat_src) < 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ g_free (utf8_dest_name);
+ return FALSE;
+ }
+ }
+
+ if (!_wapi_stat (utf8_dest_name, &stat_dest)) {
+ if (stat_dest.st_dev != stat_src.st_dev ||
+ stat_dest.st_ino != stat_src.st_ino) {
+ g_free (utf8_name);
+ g_free (utf8_dest_name);
+ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
+ return FALSE;
+ }
+ }
+
+ /* Check to make that we have delete sharing permission.
+ * See https://bugzilla.xamarin.com/show_bug.cgi?id=17009
+ *
+ * Do the checks that don't need an open file descriptor, for
+ * simplicity's sake. If we really have to do the full checks
+ * then we can implement that later.
+ */
+ if (share_allows_delete (&stat_src, &shareinfo) == FALSE) {
+ mono_w32error_set_last (ERROR_SHARING_VIOLATION);
+ return FALSE;
+ }
+ if (shareinfo)
+ file_share_release (shareinfo);
+
+ result = _wapi_rename (utf8_name, utf8_dest_name);
+ errno_copy = errno;
+
+ if (result == -1) {
+ switch(errno_copy) {
+ case EEXIST:
+ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
+ break;
+
+ case EXDEV:
+ /* Ignore here, it is dealt with below */
+ break;
+
+ case ENOENT:
+ /* We already know src exists. Must be dest that doesn't exist. */
+ _wapi_set_last_path_error_from_errno (NULL, utf8_dest_name);
+ break;
+
+ default:
+ _wapi_set_last_error_from_errno ();
+ }
+ }
+
+ g_free (utf8_name);
+ g_free (utf8_dest_name);
+
+ if (result != 0 && errno_copy == EXDEV) {
+ gint32 copy_error;
+
+ if (S_ISDIR (stat_src.st_mode)) {
+ mono_w32error_set_last (ERROR_NOT_SAME_DEVICE);
+ return FALSE;
+ }
+ /* Try a copy to the new location, and delete the source */
+ if (!mono_w32file_copy (name, dest_name, FALSE, ©_error)) {
+ /* mono_w32file_copy will set the error */
+ return(FALSE);
+ }
+
+ return(mono_w32file_delete (name));
+ }
+
+ if (result == 0) {
+ ret = TRUE;
+ }
+
+ return(ret);
+}
+
+static gboolean
+write_file (gint src_fd, gint dest_fd, struct stat *st_src, gboolean report_errors)
+{
+ gint remain, n;
+ gchar *buf, *wbuf;
+ gint buf_size = st_src->st_blksize;
+ MonoThreadInfo *info = mono_thread_info_current ();
+
+ buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size);
+ buf = (gchar *) g_malloc (buf_size);
+
+ for (;;) {
+ remain = read (src_fd, buf, buf_size);
+ if (remain < 0) {
+ if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
+ continue;
+
+ if (report_errors)
+ _wapi_set_last_error_from_errno ();
+
+ g_free (buf);
+ return FALSE;
+ }
+ if (remain == 0) {
+ break;
+ }
+
+ wbuf = buf;
+ while (remain > 0) {
+ if ((n = write (dest_fd, wbuf, remain)) < 0) {
+ if (errno == EINTR && !mono_thread_info_is_interrupt_state (info))
+ continue;
+
+ if (report_errors)
+ _wapi_set_last_error_from_errno ();
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: write failed.", __func__);
+ g_free (buf);
+ return FALSE;
+ }
+
+ remain -= n;
+ wbuf += n;
+ }
+ }
+
+ g_free (buf);
+ return TRUE ;
+}
+
+static gboolean
+CopyFile (const gunichar2 *name, const gunichar2 *dest_name, gboolean fail_if_exists)
+{
+ gchar *utf8_src, *utf8_dest;
+ gint src_fd, dest_fd;
+ struct stat st, dest_st;
+ struct utimbuf dest_time;
+ gboolean ret = TRUE;
+ gint ret_utime;
+
+ if(name==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_src = mono_unicode_to_external (name);
+ if (utf8_src == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of source returned NULL",
+ __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ if(dest_name==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dest is NULL", __func__);
+
+ g_free (utf8_src);
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_dest = mono_unicode_to_external (dest_name);
+ if (utf8_dest == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of dest returned NULL",
+ __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+
+ g_free (utf8_src);
+
+ return(FALSE);
+ }
+
+ src_fd = _wapi_open (utf8_src, O_RDONLY, 0);
+ if (src_fd < 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_src);
+
+ g_free (utf8_src);
+ g_free (utf8_dest);
+
+ return(FALSE);
+ }
+
+ if (fstat (src_fd, &st) < 0) {
+ _wapi_set_last_error_from_errno ();
+
+ g_free (utf8_src);
+ g_free (utf8_dest);
+ close (src_fd);
+
+ return(FALSE);
+ }
+
+ /* Before trying to open/create the dest, we need to report a 'file busy'
+ * error if src and dest are actually the same file. We do the check here to take
+ * advantage of the IOMAP capability */
+ if (!_wapi_stat (utf8_dest, &dest_st) && st.st_dev == dest_st.st_dev &&
+ st.st_ino == dest_st.st_ino) {
+
+ g_free (utf8_src);
+ g_free (utf8_dest);
+ close (src_fd);
+
+ mono_w32error_set_last (ERROR_SHARING_VIOLATION);
+ return (FALSE);
+ }
+
+ if (fail_if_exists) {
+ dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_EXCL, st.st_mode);
+ } else {
+ /* FIXME: it kinda sucks that this code path potentially scans
+ * the directory twice due to the weird mono_w32error_set_last()
+ * behavior. */
+ dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_TRUNC, st.st_mode);
+ if (dest_fd < 0) {
+ /* The file does not exist, try creating it */
+ dest_fd = _wapi_open (utf8_dest, O_WRONLY | O_CREAT | O_TRUNC, st.st_mode);
+ } else {
+ /* Apparently this error is set if we
+ * overwrite the dest file
+ */
+ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
+ }
+ }
+ if (dest_fd < 0) {
+ _wapi_set_last_error_from_errno ();
+
+ g_free (utf8_src);
+ g_free (utf8_dest);
+ close (src_fd);
+
+ return(FALSE);
+ }
+
+ if (!write_file (src_fd, dest_fd, &st, TRUE))
+ ret = FALSE;
+
+ close (src_fd);
+ close (dest_fd);
+
+ dest_time.modtime = st.st_mtime;
+ dest_time.actime = st.st_atime;
+ ret_utime = utime (utf8_dest, &dest_time);
+ if (ret_utime == -1)
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file [%s] utime failed: %s", __func__, utf8_dest, strerror(errno));
+
+ g_free (utf8_src);
+ g_free (utf8_dest);
+
+ return ret;
+}
+
+static gchar*
+convert_arg_to_utf8 (const gunichar2 *arg, const gchar *arg_name)
+{
+ gchar *utf8_ret;
+
+ if (arg == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s is NULL", __func__, arg_name);
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return NULL;
+ }
+
+ utf8_ret = mono_unicode_to_external (arg);
+ if (utf8_ret == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion of %s returned NULL",
+ __func__, arg_name);
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ return utf8_ret;
+}
+
+static gboolean
+ReplaceFile (const gunichar2 *replacedFileName, const gunichar2 *replacementFileName, const gunichar2 *backupFileName, guint32 replaceFlags, gpointer exclude, gpointer reserved)
+{
+ gint result, backup_fd = -1,replaced_fd = -1;
+ gchar *utf8_replacedFileName, *utf8_replacementFileName = NULL, *utf8_backupFileName = NULL;
+ struct stat stBackup;
+ gboolean ret = FALSE;
+
+ if (!(utf8_replacedFileName = convert_arg_to_utf8 (replacedFileName, "replacedFileName")))
+ return FALSE;
+ if (!(utf8_replacementFileName = convert_arg_to_utf8 (replacementFileName, "replacementFileName")))
+ goto replace_cleanup;
+ if (backupFileName != NULL) {
+ if (!(utf8_backupFileName = convert_arg_to_utf8 (backupFileName, "backupFileName")))
+ goto replace_cleanup;
+ }
+
+ if (utf8_backupFileName) {
+ // Open the backup file for read so we can restore the file if an error occurs.
+ backup_fd = _wapi_open (utf8_backupFileName, O_RDONLY, 0);
+ result = _wapi_rename (utf8_replacedFileName, utf8_backupFileName);
+ if (result == -1)
+ goto replace_cleanup;
+ }
+
+ result = _wapi_rename (utf8_replacementFileName, utf8_replacedFileName);
+ if (result == -1) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_replacementFileName);
+ _wapi_rename (utf8_backupFileName, utf8_replacedFileName);
+ if (backup_fd != -1 && !fstat (backup_fd, &stBackup)) {
+ replaced_fd = _wapi_open (utf8_backupFileName, O_WRONLY | O_CREAT | O_TRUNC,
+ stBackup.st_mode);
+
+ if (replaced_fd == -1)
+ goto replace_cleanup;
+
+ write_file (backup_fd, replaced_fd, &stBackup, FALSE);
+ }
+
+ goto replace_cleanup;
+ }
+
+ ret = TRUE;
+
+replace_cleanup:
+ g_free (utf8_replacedFileName);
+ g_free (utf8_replacementFileName);
+ g_free (utf8_backupFileName);
+ if (backup_fd != -1)
+ close (backup_fd);
+ if (replaced_fd != -1)
+ close (replaced_fd);
+ return ret;
+}
+
+static mono_mutex_t stdhandle_mutex;
+
+static gpointer
+_wapi_stdhandle_create (gint fd, const gchar *name)
+{
+ gpointer handle;
+ gint flags;
+ MonoW32HandleFile file_handle = {0};
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: creating standard handle type %s, fd %d", __func__, name, fd);
+
+#if !defined(__native_client__)
+ /* Check if fd is valid */
+ do {
+ flags = fcntl(fd, F_GETFL);
+ } while (flags == -1 && errno == EINTR);
+
+ if (flags == -1) {
+ /* Invalid fd. Not really much point checking for EBADF
+ * specifically
+ */
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: fcntl error on fd %d: %s", __func__, fd, strerror(errno));
+
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
+ return INVALID_HANDLE_VALUE;
+ }
+
+ switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ case O_RDONLY:
+ file_handle.fileaccess = GENERIC_READ;
+ break;
+ case O_WRONLY:
+ file_handle.fileaccess = GENERIC_WRITE;
+ break;
+ case O_RDWR:
+ file_handle.fileaccess = GENERIC_READ | GENERIC_WRITE;
+ break;
+ default:
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't figure out flags 0x%x", __func__, flags);
+ file_handle.fileaccess = 0;
+ break;
+ }
+#else
+ /*
+ * fcntl will return -1 in nacl, as there is no real file system API.
+ * Yet, standard streams are available.
+ */
+ file_handle.fileaccess = (fd == STDIN_FILENO) ? GENERIC_READ : GENERIC_WRITE;
+#endif
+
+ file_handle.fd = fd;
+ file_handle.filename = g_strdup(name);
+ /* some default security attributes might be needed */
+ file_handle.security_attributes = 0;
+
+ /* Apparently input handles can't be written to. (I don't
+ * know if output or error handles can't be read from.)
+ */
+ if (fd == 0)
+ file_handle.fileaccess &= ~GENERIC_WRITE;
+
+ file_handle.sharemode = 0;
+ file_handle.attrs = 0;
+
+ handle = mono_w32handle_new_fd (MONO_W32HANDLE_CONSOLE, fd, &file_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating file handle", __func__);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning handle %p", __func__, handle);
+
+ return handle;
+}
+
+enum {
+ STD_INPUT_HANDLE = -10,
+ STD_OUTPUT_HANDLE = -11,
+ STD_ERROR_HANDLE = -12,
+};
+
+static gpointer
+mono_w32file_get_std_handle (gint stdhandle)
+{
+ MonoW32HandleFile *file_handle;
+ gpointer handle;
+ gint fd;
+ const gchar *name;
+ gboolean ok;
+
+ switch(stdhandle) {
+ case STD_INPUT_HANDLE:
+ fd = 0;
+ name = "<stdin>";
+ break;
+
+ case STD_OUTPUT_HANDLE:
+ fd = 1;
+ name = "<stdout>";
+ break;
+
+ case STD_ERROR_HANDLE:
+ fd = 2;
+ name = "<stderr>";
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ handle = GINT_TO_POINTER (fd);
+
+ mono_os_mutex_lock (&stdhandle_mutex);
+
+ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_CONSOLE,
+ (gpointer *)&file_handle);
+ if (ok == FALSE) {
+ /* Need to create this console handle */
+ handle = _wapi_stdhandle_create (fd, name);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ mono_w32error_set_last (ERROR_NO_MORE_FILES);
+ goto done;
+ }
+ } else {
+ /* Add a reference to this handle */
+ mono_w32handle_ref (handle);
+ }
+
+ done:
+ mono_os_mutex_unlock (&stdhandle_mutex);
+
+ return(handle);
+}
+
+gboolean
+mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if(io_ops[type].readfile==NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(io_ops[type].readfile (handle, buffer, numbytes, bytesread));
+}
+
+gboolean
+mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if(io_ops[type].writefile==NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(io_ops[type].writefile (handle, buffer, numbytes, byteswritten));
+}
+
+gboolean
+mono_w32file_flush (gpointer handle)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if(io_ops[type].flushfile==NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(io_ops[type].flushfile (handle));
+}
+
+gboolean
+mono_w32file_truncate (gpointer handle)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if (io_ops[type].setendoffile == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(io_ops[type].setendoffile (handle));
+}
+
+guint32
+mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if (io_ops[type].seek == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(INVALID_SET_FILE_POINTER);
+ }
+
+ return(io_ops[type].seek (handle, movedistance, highmovedistance,
+ method));
+}
+
+gint
+mono_w32file_get_type(gpointer handle)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if (io_ops[type].getfiletype == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FILE_TYPE_UNKNOWN);
+ }
+
+ return(io_ops[type].getfiletype ());
+}
+
+static guint32
+GetFileSize(gpointer handle, guint32 *highsize)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if (io_ops[type].getfilesize == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(INVALID_FILE_SIZE);
+ }
+
+ return(io_ops[type].getfilesize (handle, highsize));
+}
+
+gboolean
+mono_w32file_get_times(gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if (io_ops[type].getfiletime == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(io_ops[type].getfiletime (handle, create_time, access_time,
+ write_time));
+}
+
+gboolean
+mono_w32file_set_times(gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
+{
+ MonoW32HandleType type;
+
+ type = mono_w32handle_get_type (handle);
+
+ if (io_ops[type].setfiletime == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ return(io_ops[type].setfiletime (handle, create_time, access_time,
+ write_time));
+}
+
+/* A tick is a 100-nanosecond interval. File time epoch is Midnight,
+ * January 1 1601 GMT
+ */
+
+#define TICKS_PER_MILLISECOND 10000L
+#define TICKS_PER_SECOND 10000000L
+#define TICKS_PER_MINUTE 600000000L
+#define TICKS_PER_HOUR 36000000000LL
+#define TICKS_PER_DAY 864000000000LL
+
+#define isleap(y) ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
+
+static const guint16 mon_yday[2][13]={
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+ {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
+};
+
+gboolean
+mono_w32file_filetime_to_systemtime(const FILETIME *file_time, SYSTEMTIME *system_time)
+{
+ gint64 file_ticks, totaldays, rem, y;
+ const guint16 *ip;
+
+ if(system_time==NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: system_time NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ file_ticks=((gint64)file_time->dwHighDateTime << 32) +
+ file_time->dwLowDateTime;
+
+ /* Really compares if file_ticks>=0x8000000000000000
+ * (LLONG_MAX+1) but we're working with a signed value for the
+ * year and day calculation to work later
+ */
+ if(file_ticks<0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file_time too big", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ totaldays=(file_ticks / TICKS_PER_DAY);
+ rem = file_ticks % TICKS_PER_DAY;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld rem: %lld", __func__, totaldays, rem);
+
+ system_time->wHour=rem/TICKS_PER_HOUR;
+ rem %= TICKS_PER_HOUR;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Hour: %d rem: %lld", __func__, system_time->wHour, rem);
+
+ system_time->wMinute = rem / TICKS_PER_MINUTE;
+ rem %= TICKS_PER_MINUTE;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Minute: %d rem: %lld", __func__, system_time->wMinute,
+ rem);
+
+ system_time->wSecond = rem / TICKS_PER_SECOND;
+ rem %= TICKS_PER_SECOND;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Second: %d rem: %lld", __func__, system_time->wSecond,
+ rem);
+
+ system_time->wMilliseconds = rem / TICKS_PER_MILLISECOND;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Milliseconds: %d", __func__,
+ system_time->wMilliseconds);
+
+ /* January 1, 1601 was a Monday, according to Emacs calendar */
+ system_time->wDayOfWeek = ((1 + totaldays) % 7) + 1;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day of week: %d", __func__, system_time->wDayOfWeek);
+
+ /* This algorithm to find year and month given days from epoch
+ * from glibc
+ */
+ y=1601;
+
+#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define LEAPS_THRU_END_OF(y) (DIV(y, 4) - DIV (y, 100) + DIV (y, 400))
+
+ while(totaldays < 0 || totaldays >= (isleap(y)?366:365)) {
+ /* Guess a corrected year, assuming 365 days per year */
+ gint64 yg = y + totaldays / 365 - (totaldays % 365 < 0);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld yg: %lld y: %lld", __func__,
+ totaldays, yg,
+ y);
+ g_message("%s: LEAPS(yg): %lld LEAPS(y): %lld", __func__,
+ LEAPS_THRU_END_OF(yg-1), LEAPS_THRU_END_OF(y-1));
+
+ /* Adjust days and y to match the guessed year. */
+ totaldays -= ((yg - y) * 365
+ + LEAPS_THRU_END_OF (yg - 1)
+ - LEAPS_THRU_END_OF (y - 1));
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
+ y = yg;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: y: %lld", __func__, y);
+ }
+
+ system_time->wYear = y;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Year: %d", __func__, system_time->wYear);
+
+ ip = mon_yday[isleap(y)];
+
+ for(y=11; totaldays < ip[y]; --y) {
+ continue;
+ }
+ totaldays-=ip[y];
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: totaldays: %lld", __func__, totaldays);
+
+ system_time->wMonth = y + 1;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Month: %d", __func__, system_time->wMonth);
+
+ system_time->wDay = totaldays + 1;
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Day: %d", __func__, system_time->wDay);
+
+ return(TRUE);
+}
+
+gpointer
+mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data)
+{
+ MonoW32HandleFind find_handle = {0};
+ gpointer handle;
+ gchar *utf8_pattern = NULL, *dir_part, *entry_part;
+ gint result;
+
+ if (pattern == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pattern is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_PATH_NOT_FOUND);
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ utf8_pattern = mono_unicode_to_external (pattern);
+ if (utf8_pattern == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: looking for [%s]", __func__, utf8_pattern);
+
+ /* Figure out which bit of the pattern is the directory */
+ dir_part = _wapi_dirname (utf8_pattern);
+ entry_part = _wapi_basename (utf8_pattern);
+
+#if 0
+ /* Don't do this check for now, it breaks if directories
+ * really do have metachars in their names (see bug 58116).
+ * FIXME: Figure out a better solution to keep some checks...
+ */
+ if (strchr (dir_part, '*') || strchr (dir_part, '?')) {
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ g_free (dir_part);
+ g_free (entry_part);
+ g_free (utf8_pattern);
+ return(INVALID_HANDLE_VALUE);
+ }
+#endif
+
+ /* The pattern can specify a directory or a set of files.
+ *
+ * The pattern can have wildcard characters ? and *, but only
+ * in the section after the last directory delimiter. (Return
+ * ERROR_INVALID_NAME if there are wildcards in earlier path
+ * sections.) "*" has the usual 0-or-more chars meaning. "?"
+ * means "match one character", "??" seems to mean "match one
+ * or two characters", "???" seems to mean "match one, two or
+ * three characters", etc. Windows will also try and match
+ * the mangled "short name" of files, so 8 character patterns
+ * with wildcards will show some surprising results.
+ *
+ * All the written documentation I can find says that '?'
+ * should only match one character, and doesn't mention '??',
+ * '???' etc. I'm going to assume that the strict behaviour
+ * (ie '???' means three and only three characters) is the
+ * correct one, because that lets me use fnmatch(3) rather
+ * than mess around with regexes.
+ */
+
+ find_handle.namelist = NULL;
+ result = _wapi_io_scandir (dir_part, entry_part,
+ &find_handle.namelist);
+
+ if (result == 0) {
+ /* No files, which windows seems to call
+ * FILE_NOT_FOUND
+ */
+ mono_w32error_set_last (ERROR_FILE_NOT_FOUND);
+ g_free (utf8_pattern);
+ g_free (entry_part);
+ g_free (dir_part);
+ return (INVALID_HANDLE_VALUE);
+ }
+
+ if (result < 0) {
+ _wapi_set_last_path_error_from_errno (dir_part, NULL);
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: scandir error: %s", __func__, g_strerror (errno));
+ g_free (utf8_pattern);
+ g_free (entry_part);
+ g_free (dir_part);
+ return (INVALID_HANDLE_VALUE);
+ }
+
+ g_free (utf8_pattern);
+ g_free (entry_part);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Got %d matches", __func__, result);
+
+ find_handle.dir_part = dir_part;
+ find_handle.num = result;
+ find_handle.count = 0;
+
+ handle = mono_w32handle_new (MONO_W32HANDLE_FIND, &find_handle);
+ if (handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating find handle", __func__);
+ g_free (dir_part);
+ g_free (entry_part);
+ g_free (utf8_pattern);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
+
+ return(INVALID_HANDLE_VALUE);
+ }
+
+ if (handle != INVALID_HANDLE_VALUE &&
+ !mono_w32file_find_next (handle, find_data)) {
+ mono_w32file_find_close (handle);
+ mono_w32error_set_last (ERROR_NO_MORE_FILES);
+ handle = INVALID_HANDLE_VALUE;
+ }
+
+ return (handle);
+}
+
+gboolean
+mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data)
+{
+ MonoW32HandleFind *find_handle;
+ gboolean ok;
+ struct stat buf, linkbuf;
+ gint result;
+ gchar *filename;
+ gchar *utf8_filename, *utf8_basename;
+ gunichar2 *utf16_basename;
+ time_t create_time;
+ glong bytes;
+ gboolean ret = FALSE;
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
+ (gpointer *)&find_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up find handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ mono_w32handle_lock_handle (handle);
+
+retry:
+ if (find_handle->count >= find_handle->num) {
+ mono_w32error_set_last (ERROR_NO_MORE_FILES);
+ goto cleanup;
+ }
+
+ /* stat next match */
+
+ filename = g_build_filename (find_handle->dir_part, find_handle->namelist[find_handle->count ++], NULL);
+
+ result = _wapi_stat (filename, &buf);
+ if (result == -1 && errno == ENOENT) {
+ /* Might be a dangling symlink */
+ result = _wapi_lstat (filename, &buf);
+ }
+
+ if (result != 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: stat failed: %s", __func__, filename);
+
+ g_free (filename);
+ goto retry;
+ }
+
+#ifndef __native_client__
+ result = _wapi_lstat (filename, &linkbuf);
+ if (result != 0) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: lstat failed: %s", __func__, filename);
+
+ g_free (filename);
+ goto retry;
+ }
+#endif
+
+ utf8_filename = mono_utf8_from_external (filename);
+ if (utf8_filename == NULL) {
+ /* We couldn't turn this filename into utf8 (eg the
+ * encoding of the name wasn't convertible), so just
+ * ignore it.
+ */
+ g_warning ("%s: Bad encoding for '%s'\nConsider using MONO_EXTERNAL_ENCODINGS\n", __func__, filename);
+
+ g_free (filename);
+ goto retry;
+ }
+ g_free (filename);
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Found [%s]", __func__, utf8_filename);
+
+ /* fill data block */
+
+ if (buf.st_mtime < buf.st_ctime)
+ create_time = buf.st_mtime;
+ else
+ create_time = buf.st_ctime;
+
+#ifdef __native_client__
+ find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, NULL);
+#else
+ find_data->dwFileAttributes = _wapi_stat_to_file_attributes (utf8_filename, &buf, &linkbuf);
+#endif
+
+ time_t_to_filetime (create_time, &find_data->ftCreationTime);
+ time_t_to_filetime (buf.st_atime, &find_data->ftLastAccessTime);
+ time_t_to_filetime (buf.st_mtime, &find_data->ftLastWriteTime);
+
+ if (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ find_data->nFileSizeHigh = 0;
+ find_data->nFileSizeLow = 0;
+ } else {
+ find_data->nFileSizeHigh = buf.st_size >> 32;
+ find_data->nFileSizeLow = buf.st_size & 0xFFFFFFFF;
+ }
+
+ find_data->dwReserved0 = 0;
+ find_data->dwReserved1 = 0;
+
+ utf8_basename = _wapi_basename (utf8_filename);
+ utf16_basename = g_utf8_to_utf16 (utf8_basename, -1, NULL, &bytes,
+ NULL);
+ if(utf16_basename==NULL) {
+ g_free (utf8_basename);
+ g_free (utf8_filename);
+ goto retry;
+ }
+ ret = TRUE;
+
+ /* utf16 is 2 * utf8 */
+ bytes *= 2;
+
+ memset (find_data->cFileName, '\0', (MAX_PATH*2));
+
+ /* Truncating a utf16 string like this might leave the last
+ * gchar incomplete
+ */
+ memcpy (find_data->cFileName, utf16_basename,
+ bytes<(MAX_PATH*2)-2?bytes:(MAX_PATH*2)-2);
+
+ find_data->cAlternateFileName [0] = 0; /* not used */
+
+ g_free (utf8_basename);
+ g_free (utf8_filename);
+ g_free (utf16_basename);
+
+cleanup:
+ mono_w32handle_unlock_handle (handle);
+
+ return(ret);
+}
+
+gboolean
+mono_w32file_find_close (gpointer handle)
+{
+ MonoW32HandleFind *find_handle;
+ gboolean ok;
+
+ if (handle == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ ok=mono_w32handle_lookup (handle, MONO_W32HANDLE_FIND,
+ (gpointer *)&find_handle);
+ if(ok==FALSE) {
+ g_warning ("%s: error looking up find handle %p", __func__,
+ handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return(FALSE);
+ }
+
+ mono_w32handle_lock_handle (handle);
+
+ g_strfreev (find_handle->namelist);
+ g_free (find_handle->dir_part);
+
+ mono_w32handle_unlock_handle (handle);
+
+ mono_w32handle_unref (handle);
+
+ return(TRUE);
+}
+
+gboolean
+mono_w32file_create_directory (const gunichar2 *name)
+{
+ gchar *utf8_name;
+ gint result;
+
+ if (name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_name = mono_unicode_to_external (name);
+ if (utf8_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return FALSE;
+ }
+
+ result = _wapi_mkdir (utf8_name, 0777);
+
+ if (result == 0) {
+ g_free (utf8_name);
+ return TRUE;
+ }
+
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ return FALSE;
+}
+
+gboolean
+mono_w32file_remove_directory (const gunichar2 *name)
+{
+ gchar *utf8_name;
+ gint result;
+
+ if (name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_name = mono_unicode_to_external (name);
+ if (utf8_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return FALSE;
+ }
+
+ result = _wapi_rmdir (utf8_name);
+ if (result == -1) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+
+ return(FALSE);
+ }
+ g_free (utf8_name);
+
+ return(TRUE);
+}
+
+guint32
+mono_w32file_get_attributes (const gunichar2 *name)
+{
+ gchar *utf8_name;
+ struct stat buf, linkbuf;
+ gint result;
+ guint32 ret;
+
+ if (name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_name = mono_unicode_to_external (name);
+ if (utf8_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return (INVALID_FILE_ATTRIBUTES);
+ }
+
+ result = _wapi_stat (utf8_name, &buf);
+ if (result == -1 && errno == ENOENT) {
+ /* Might be a dangling symlink... */
+ result = _wapi_lstat (utf8_name, &buf);
+ }
+
+ if (result != 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ return (INVALID_FILE_ATTRIBUTES);
+ }
+
+#ifndef __native_client__
+ result = _wapi_lstat (utf8_name, &linkbuf);
+ if (result != 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ return (INVALID_FILE_ATTRIBUTES);
+ }
+#endif
+
+#ifdef __native_client__
+ ret = _wapi_stat_to_file_attributes (utf8_name, &buf, NULL);
+#else
+ ret = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
+#endif
+
+ g_free (utf8_name);
+
+ return(ret);
+}
+
+gboolean
+mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
+{
+ gchar *utf8_name;
+
+ struct stat buf, linkbuf;
+ gint result;
+
+ if (name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_name = mono_unicode_to_external (name);
+ if (utf8_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ result = _wapi_stat (utf8_name, &buf);
+ if (result == -1 && errno == ENOENT) {
+ /* Might be a dangling symlink... */
+ result = _wapi_lstat (utf8_name, &buf);
+ }
+
+ if (result != 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ return FALSE;
+ }
+
+ result = _wapi_lstat (utf8_name, &linkbuf);
+ if (result != 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ return(FALSE);
+ }
+
+ /* fill stat block */
+
+ stat->attributes = _wapi_stat_to_file_attributes (utf8_name, &buf, &linkbuf);
+ stat->creation_time = (((guint64) (buf.st_mtime < buf.st_ctime ? buf.st_mtime : buf.st_ctime)) * 10 * 1000 * 1000) + 116444736000000000ULL;
+ stat->last_access_time = (((guint64) (buf.st_atime)) * 10 * 1000 * 1000) + 116444736000000000ULL;
+ stat->last_write_time = (((guint64) (buf.st_mtime)) * 10 * 1000 * 1000) + 116444736000000000ULL;
+ stat->length = (stat->attributes & FILE_ATTRIBUTE_DIRECTORY) ? 0 : buf.st_size;
+
+ g_free (utf8_name);
+ return TRUE;
+}
+
+gboolean
+mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
+{
+ /* FIXME: think of something clever to do on unix */
+ gchar *utf8_name;
+ struct stat buf;
+ gint result;
+
+ /*
+ * Currently we only handle one *internal* case, with a value that is
+ * not standard: 0x80000000, which means `set executable bit'
+ */
+
+ if (name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: name is NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+
+ utf8_name = mono_unicode_to_external (name);
+ if (utf8_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return FALSE;
+ }
+
+ result = _wapi_stat (utf8_name, &buf);
+ if (result == -1 && errno == ENOENT) {
+ /* Might be a dangling symlink... */
+ result = _wapi_lstat (utf8_name, &buf);
+ }
+
+ if (result != 0) {
+ _wapi_set_last_path_error_from_errno (NULL, utf8_name);
+ g_free (utf8_name);
+ return FALSE;
+ }
+
+ /* Contrary to the documentation, ms allows NORMAL to be
+ * specified along with other attributes, so dont bother to
+ * catch that case here.
+ */
+ if (attrs & FILE_ATTRIBUTE_READONLY) {
+ result = _wapi_chmod (utf8_name, buf.st_mode & ~(S_IWUSR | S_IWOTH | S_IWGRP));
+ } else {
+ result = _wapi_chmod (utf8_name, buf.st_mode | S_IWUSR);
+ }
+
+ /* Ignore the other attributes for now */
+
+ if (attrs & 0x80000000){
+ mode_t exec_mask = 0;
+
+ if ((buf.st_mode & S_IRUSR) != 0)
+ exec_mask |= S_IXUSR;
+
+ if ((buf.st_mode & S_IRGRP) != 0)
+ exec_mask |= S_IXGRP;
+
+ if ((buf.st_mode & S_IROTH) != 0)
+ exec_mask |= S_IXOTH;
+
+ result = chmod (utf8_name, buf.st_mode | exec_mask);
+ }
+ /* Don't bother to reset executable (might need to change this
+ * policy)
+ */
+
+ g_free (utf8_name);
+
+ return(TRUE);
+}
+
+guint32
+mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
+{
+ gunichar2 *utf16_path;
+ glong count;
+ gsize bytes;
+
+#ifdef __native_client__
+ gchar *path = g_get_current_dir ();
+ if (length < strlen(path) + 1 || path == NULL)
+ return 0;
+ memcpy (buffer, path, strlen(path) + 1);
+#else
+ if (getcwd ((gchar*)buffer, length) == NULL) {
+ if (errno == ERANGE) { /*buffer length is not big enough */
+ gchar *path = g_get_current_dir (); /*FIXME g_get_current_dir doesn't work with broken paths and calling it just to know the path length is silly*/
+ if (path == NULL)
+ return 0;
+ utf16_path = mono_unicode_from_external (path, &bytes);
+ g_free (utf16_path);
+ g_free (path);
+ return (bytes/2)+1;
+ }
+ _wapi_set_last_error_from_errno ();
+ return 0;
+ }
+#endif
+
+ utf16_path = mono_unicode_from_external ((gchar*)buffer, &bytes);
+ count = (bytes/2)+1;
+ g_assert (count <= length); /*getcwd must have failed before with ERANGE*/
+
+ /* Add the terminator */
+ memset (buffer, '\0', bytes+2);
+ memcpy (buffer, utf16_path, bytes);
+
+ g_free (utf16_path);
+
+ return count;
+}
+
+gboolean
+mono_w32file_set_cwd (const gunichar2 *path)
+{
+ gchar *utf8_path;
+ gboolean result;
+
+ if (path == NULL) {
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return(FALSE);
+ }
+
+ utf8_path = mono_unicode_to_external (path);
+ if (_wapi_chdir (utf8_path) != 0) {
+ _wapi_set_last_error_from_errno ();
+ result = FALSE;
+ }
+ else
+ result = TRUE;
+
+ g_free (utf8_path);
+ return result;
+}
+
+gboolean
+mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
+{
+ MonoW32HandleFile pipe_read_handle = {0};
+ MonoW32HandleFile pipe_write_handle = {0};
+ gpointer read_handle;
+ gpointer write_handle;
+ gint filedes[2];
+ gint ret;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Creating pipe", __func__);
+
+ ret=pipe (filedes);
+ if(ret==-1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error creating pipe: %s", __func__,
+ strerror (errno));
+
+ _wapi_set_last_error_from_errno ();
+ return(FALSE);
+ }
+
+ if (filedes[0] >= mono_w32handle_fd_reserve ||
+ filedes[1] >= mono_w32handle_fd_reserve) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__);
+
+ mono_w32error_set_last (ERROR_TOO_MANY_OPEN_FILES);
+
+ close (filedes[0]);
+ close (filedes[1]);
+
+ return(FALSE);
+ }
+
+ /* filedes[0] is open for reading, filedes[1] for writing */
+
+ pipe_read_handle.fd = filedes [0];
+ pipe_read_handle.fileaccess = GENERIC_READ;
+ read_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[0],
+ &pipe_read_handle);
+ if (read_handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating pipe read handle", __func__);
+ close (filedes[0]);
+ close (filedes[1]);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
+
+ return(FALSE);
+ }
+
+ pipe_write_handle.fd = filedes [1];
+ pipe_write_handle.fileaccess = GENERIC_WRITE;
+ write_handle = mono_w32handle_new_fd (MONO_W32HANDLE_PIPE, filedes[1],
+ &pipe_write_handle);
+ if (write_handle == INVALID_HANDLE_VALUE) {
+ g_warning ("%s: error creating pipe write handle", __func__);
+ mono_w32handle_unref (read_handle);
+
+ close (filedes[0]);
+ close (filedes[1]);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
+
+ return(FALSE);
+ }
+
+ *readpipe = read_handle;
+ *writepipe = write_handle;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Returning pipe: read handle %p, write handle %p",
+ __func__, read_handle, write_handle);
+
+ return(TRUE);
+}
+
+#ifdef HAVE_GETFSSTAT
+/* Darwin has getfsstat */
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+ struct statfs *stats;
+ gint size, n, i;
+ gunichar2 *dir;
+ glong length, total = 0;
+
+ n = getfsstat (NULL, 0, MNT_NOWAIT);
+ if (n == -1)
+ return 0;
+ size = n * sizeof (struct statfs);
+ stats = (struct statfs *) g_malloc (size);
+ if (stats == NULL)
+ return 0;
+ if (getfsstat (stats, size, MNT_NOWAIT) == -1){
+ g_free (stats);
+ return 0;
+ }
+ for (i = 0; i < n; i++){
+ dir = g_utf8_to_utf16 (stats [i].f_mntonname, -1, NULL, &length, NULL);
+ if (total + length < len){
+ memcpy (buf + total, dir, sizeof (gunichar2) * length);
+ buf [total+length] = 0;
+ }
+ g_free (dir);
+ total += length + 1;
+ }
+ if (total < len)
+ buf [total] = 0;
+ total++;
+ g_free (stats);
+ return total;
+}
+#else
+/* In-place octal sequence replacement */
+static void
+unescape_octal (gchar *str)
+{
+ gchar *rptr;
+ gchar *wptr;
+
+ if (str == NULL)
+ return;
+
+ rptr = wptr = str;
+ while (*rptr != '\0') {
+ if (*rptr == '\\') {
+ gchar c;
+ rptr++;
+ c = (*(rptr++) - '0') << 6;
+ c += (*(rptr++) - '0') << 3;
+ c += *(rptr++) - '0';
+ *wptr++ = c;
+ } else if (wptr != rptr) {
+ *wptr++ = *rptr++;
+ } else {
+ rptr++; wptr++;
+ }
+ }
+ *wptr = '\0';
+}
+static gint32 GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf);
+
+#if __linux__
+#define GET_LOGICAL_DRIVE_STRINGS_BUFFER 512
+#define GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER 512
+#define GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER 64
+
+typedef struct
+{
+ glong total;
+ guint32 buffer_index;
+ guint32 mountpoint_index;
+ guint32 field_number;
+ guint32 allocated_size;
+ guint32 fsname_index;
+ guint32 fstype_index;
+ gchar mountpoint [GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER + 1];
+ gchar *mountpoint_allocated;
+ gchar buffer [GET_LOGICAL_DRIVE_STRINGS_BUFFER];
+ gchar fsname [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
+ gchar fstype [GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER + 1];
+ ssize_t nbytes;
+ gchar delimiter;
+ gboolean check_mount_source;
+} LinuxMountInfoParseState;
+
+static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
+static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
+static void append_to_mountpoint (LinuxMountInfoParseState *state);
+static gboolean add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state);
+
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+ gint fd;
+ gint32 ret = 0;
+ LinuxMountInfoParseState state;
+ gboolean (*parser)(guint32, gunichar2*, LinuxMountInfoParseState*) = NULL;
+
+ memset (buf, 0, len * sizeof (gunichar2));
+ fd = open ("/proc/self/mountinfo", O_RDONLY);
+ if (fd != -1)
+ parser = GetLogicalDriveStrings_MountInfo;
+ else {
+ fd = open ("/proc/mounts", O_RDONLY);
+ if (fd != -1)
+ parser = GetLogicalDriveStrings_Mounts;
+ }
+
+ if (!parser) {
+ ret = GetLogicalDriveStrings_Mtab (len, buf);
+ goto done_and_out;
+ }
+
+ memset (&state, 0, sizeof (LinuxMountInfoParseState));
+ state.field_number = 1;
+ state.delimiter = ' ';
+
+ while ((state.nbytes = read (fd, state.buffer, GET_LOGICAL_DRIVE_STRINGS_BUFFER)) > 0) {
+ state.buffer_index = 0;
+
+ while ((*parser)(len, buf, &state)) {
+ if (state.buffer [state.buffer_index] == '\n') {
+ gboolean quit = add_drive_string (len, buf, &state);
+ state.field_number = 1;
+ state.buffer_index++;
+ if (state.mountpoint_allocated) {
+ g_free (state.mountpoint_allocated);
+ state.mountpoint_allocated = NULL;
+ }
+ if (quit) {
+ ret = state.total;
+ goto done_and_out;
+ }
+ }
+ }
+ };
+ ret = state.total;
+
+ done_and_out:
+ if (fd != -1)
+ close (fd);
+ return ret;
+}
+
+static gboolean GetLogicalDriveStrings_Mounts (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
+{
+ gchar *ptr;
+
+ if (state->field_number == 1)
+ state->check_mount_source = TRUE;
+
+ while (state->buffer_index < (guint32)state->nbytes) {
+ if (state->buffer [state->buffer_index] == state->delimiter) {
+ state->field_number++;
+ switch (state->field_number) {
+ case 2:
+ state->mountpoint_index = 0;
+ break;
+
+ case 3:
+ if (state->mountpoint_allocated)
+ state->mountpoint_allocated [state->mountpoint_index] = 0;
+ else
+ state->mountpoint [state->mountpoint_index] = 0;
+ break;
+
+ default:
+ ptr = (gchar*)memchr (state->buffer + state->buffer_index, '\n', GET_LOGICAL_DRIVE_STRINGS_BUFFER - state->buffer_index);
+ if (ptr)
+ state->buffer_index = (ptr - (gchar*)state->buffer) - 1;
+ else
+ state->buffer_index = state->nbytes;
+ return TRUE;
+ }
+ state->buffer_index++;
+ continue;
+ } else if (state->buffer [state->buffer_index] == '\n')
+ return TRUE;
+
+ switch (state->field_number) {
+ case 1:
+ if (state->check_mount_source) {
+ if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
+ /* We can ignore the rest, it's a device
+ * path */
+ state->check_mount_source = FALSE;
+ state->fsname [state->fsname_index++] = '/';
+ break;
+ }
+ if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+ state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
+ }
+ break;
+
+ case 2:
+ append_to_mountpoint (state);
+ break;
+
+ case 3:
+ if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+ state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
+ break;
+ }
+
+ state->buffer_index++;
+ }
+
+ return FALSE;
+}
+
+static gboolean GetLogicalDriveStrings_MountInfo (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
+{
+ while (state->buffer_index < (guint32)state->nbytes) {
+ if (state->buffer [state->buffer_index] == state->delimiter) {
+ state->field_number++;
+ switch (state->field_number) {
+ case 5:
+ state->mountpoint_index = 0;
+ break;
+
+ case 6:
+ if (state->mountpoint_allocated)
+ state->mountpoint_allocated [state->mountpoint_index] = 0;
+ else
+ state->mountpoint [state->mountpoint_index] = 0;
+ break;
+
+ case 7:
+ state->delimiter = '-';
+ break;
+
+ case 8:
+ state->delimiter = ' ';
+ break;
+
+ case 10:
+ state->check_mount_source = TRUE;
+ break;
+ }
+ state->buffer_index++;
+ continue;
+ } else if (state->buffer [state->buffer_index] == '\n')
+ return TRUE;
+
+ switch (state->field_number) {
+ case 5:
+ append_to_mountpoint (state);
+ break;
+
+ case 9:
+ if (state->fstype_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+ state->fstype [state->fstype_index++] = state->buffer [state->buffer_index];
+ break;
+
+ case 10:
+ if (state->check_mount_source) {
+ if (state->fsname_index == 0 && state->buffer [state->buffer_index] == '/') {
+ /* We can ignore the rest, it's a device
+ * path */
+ state->check_mount_source = FALSE;
+ state->fsname [state->fsname_index++] = '/';
+ break;
+ }
+ if (state->fsname_index < GET_LOGICAL_DRIVE_STRINGS_FSNAME_BUFFER)
+ state->fsname [state->fsname_index++] = state->buffer [state->buffer_index];
+ }
+ break;
+ }
+
+ state->buffer_index++;
+ }
+
+ return FALSE;
+}
+
+static void
+append_to_mountpoint (LinuxMountInfoParseState *state)
+{
+ gchar ch = state->buffer [state->buffer_index];
+ if (state->mountpoint_allocated) {
+ if (state->mountpoint_index >= state->allocated_size) {
+ guint32 newsize = (state->allocated_size << 1) + 1;
+ gchar *newbuf = (gchar *)g_malloc0 (newsize * sizeof (gchar));
+
+ memcpy (newbuf, state->mountpoint_allocated, state->mountpoint_index);
+ g_free (state->mountpoint_allocated);
+ state->mountpoint_allocated = newbuf;
+ state->allocated_size = newsize;
+ }
+ state->mountpoint_allocated [state->mountpoint_index++] = ch;
+ } else {
+ if (state->mountpoint_index >= GET_LOGICAL_DRIVE_STRINGS_MOUNTPOINT_BUFFER) {
+ state->allocated_size = (state->mountpoint_index << 1) + 1;
+ state->mountpoint_allocated = (gchar *)g_malloc0 (state->allocated_size * sizeof (gchar));
+ memcpy (state->mountpoint_allocated, state->mountpoint, state->mountpoint_index);
+ state->mountpoint_allocated [state->mountpoint_index++] = ch;
+ } else
+ state->mountpoint [state->mountpoint_index++] = ch;
+ }
+}
+
+static gboolean
+add_drive_string (guint32 len, gunichar2 *buf, LinuxMountInfoParseState *state)
+{
+ gboolean quit = FALSE;
+ gboolean ignore_entry;
+
+ if (state->fsname_index == 1 && state->fsname [0] == '/')
+ ignore_entry = FALSE;
+ else if (memcmp ("overlay", state->fsname, state->fsname_index) == 0 ||
+ memcmp ("aufs", state->fstype, state->fstype_index) == 0) {
+ /* Don't ignore overlayfs and aufs - these might be used on Docker
+ * (https://bugzilla.xamarin.com/show_bug.cgi?id=31021) */
+ ignore_entry = FALSE;
+ } else if (state->fsname_index == 0 || memcmp ("none", state->fsname, state->fsname_index) == 0) {
+ ignore_entry = TRUE;
+ } else if (state->fstype_index >= 5 && memcmp ("fuse.", state->fstype, 5) == 0) {
+ /* Ignore GNOME's gvfs */
+ if (state->fstype_index == 21 && memcmp ("fuse.gvfs-fuse-daemon", state->fstype, state->fstype_index) == 0)
+ ignore_entry = TRUE;
+ else
+ ignore_entry = FALSE;
+ } else if (state->fstype_index == 3 && memcmp ("nfs", state->fstype, state->fstype_index) == 0)
+ ignore_entry = FALSE;
+ else
+ ignore_entry = TRUE;
+
+ if (!ignore_entry) {
+ gunichar2 *dir;
+ glong length;
+ gchar *mountpoint = state->mountpoint_allocated ? state->mountpoint_allocated : state->mountpoint;
+
+ unescape_octal (mountpoint);
+ dir = g_utf8_to_utf16 (mountpoint, -1, NULL, &length, NULL);
+ if (state->total + length + 1 > len) {
+ quit = TRUE;
+ state->total = len * 2;
+ } else {
+ length++;
+ memcpy (buf + state->total, dir, sizeof (gunichar2) * length);
+ state->total += length;
+ }
+ g_free (dir);
+ }
+ state->fsname_index = 0;
+ state->fstype_index = 0;
+
+ return quit;
+}
+#else
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+ return GetLogicalDriveStrings_Mtab (len, buf);
+}
+#endif
+static gint32
+GetLogicalDriveStrings_Mtab (guint32 len, gunichar2 *buf)
+{
+ FILE *fp;
+ gunichar2 *ptr, *dir;
+ glong length, total = 0;
+ gchar buffer [512];
+ gchar **splitted;
+
+ memset (buf, 0, sizeof (gunichar2) * (len + 1));
+ buf [0] = '/';
+ buf [1] = 0;
+ buf [2] = 0;
+
+ /* Sigh, mntent and friends don't work well.
+ * It stops on the first line that doesn't begin with a '/'.
+ * (linux 2.6.5, libc 2.3.2.ds1-12) - Gonz */
+ fp = fopen ("/etc/mtab", "rt");
+ if (fp == NULL) {
+ fp = fopen ("/etc/mnttab", "rt");
+ if (fp == NULL)
+ return 1;
+ }
+
+ ptr = buf;
+ while (fgets (buffer, 512, fp) != NULL) {
+ if (*buffer != '/')
+ continue;
+
+ splitted = g_strsplit (buffer, " ", 0);
+ if (!*splitted || !*(splitted + 1)) {
+ g_strfreev (splitted);
+ continue;
+ }
+
+ unescape_octal (*(splitted + 1));
+ dir = g_utf8_to_utf16 (*(splitted + 1), -1, NULL, &length, NULL);
+ g_strfreev (splitted);
+ if (total + length + 1 > len) {
+ fclose (fp);
+ g_free (dir);
+ return len * 2; /* guess */
+ }
+
+ memcpy (ptr + total, dir, sizeof (gunichar2) * length);
+ g_free (dir);
+ total += length + 1;
+ }
+
+ fclose (fp);
+ return total;
+/* Commented out, does not work with my mtab!!! - Gonz */
+#ifdef NOTENABLED /* HAVE_MNTENT_H */
+{
+ FILE *fp;
+ struct mntent *mnt;
+ gunichar2 *ptr, *dir;
+ glong len, total = 0;
+
+
+ fp = setmntent ("/etc/mtab", "rt");
+ if (fp == NULL) {
+ fp = setmntent ("/etc/mnttab", "rt");
+ if (fp == NULL)
+ return;
+ }
+
+ ptr = buf;
+ while ((mnt = getmntent (fp)) != NULL) {
+ g_print ("GOT %s\n", mnt->mnt_dir);
+ dir = g_utf8_to_utf16 (mnt->mnt_dir, &len, NULL, NULL, NULL);
+ if (total + len + 1 > len) {
+ return len * 2; /* guess */
+ }
+
+ memcpy (ptr + total, dir, sizeof (gunichar2) * len);
+ g_free (dir);
+ total += len + 1;
+ }
+
+ endmntent (fp);
+ return total;
+}
+#endif
+}
+#endif
+
+#if defined(HAVE_STATVFS) || defined(HAVE_STATFS)
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
+{
+#ifdef HAVE_STATVFS
+ struct statvfs fsstat;
+#elif defined(HAVE_STATFS)
+ struct statfs fsstat;
+#endif
+ gboolean isreadonly;
+ gchar *utf8_path_name;
+ gint ret;
+ unsigned long block_size;
+
+ if (path_name == NULL) {
+ utf8_path_name = g_strdup (g_get_current_dir());
+ if (utf8_path_name == NULL) {
+ mono_w32error_set_last (ERROR_DIRECTORY);
+ return(FALSE);
+ }
+ }
+ else {
+ utf8_path_name = mono_unicode_to_external (path_name);
+ if (utf8_path_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+
+ mono_w32error_set_last (ERROR_INVALID_NAME);
+ return(FALSE);
+ }
+ }
+
+ do {
+#ifdef HAVE_STATVFS
+ ret = statvfs (utf8_path_name, &fsstat);
+ isreadonly = ((fsstat.f_flag & ST_RDONLY) == ST_RDONLY);
+ block_size = fsstat.f_frsize;
+#elif defined(HAVE_STATFS)
+ ret = statfs (utf8_path_name, &fsstat);
+#if defined (MNT_RDONLY)
+ isreadonly = ((fsstat.f_flags & MNT_RDONLY) == MNT_RDONLY);
+#elif defined (MS_RDONLY)
+ isreadonly = ((fsstat.f_flags & MS_RDONLY) == MS_RDONLY);
+#endif
+ block_size = fsstat.f_bsize;
+#endif
+ } while(ret == -1 && errno == EINTR);
+
+ g_free(utf8_path_name);
+
+ if (ret == -1) {
+ _wapi_set_last_error_from_errno ();
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: statvfs failed: %s", __func__, strerror (errno));
+ return(FALSE);
+ }
+
+ /* total number of free bytes for non-root */
+ if (free_bytes_avail != NULL) {
+ if (isreadonly) {
+ *free_bytes_avail = 0;
+ }
+ else {
+ *free_bytes_avail = block_size * (guint64)fsstat.f_bavail;
+ }
+ }
+
+ /* total number of bytes available for non-root */
+ if (total_number_of_bytes != NULL) {
+ *total_number_of_bytes = block_size * (guint64)fsstat.f_blocks;
+ }
+
+ /* total number of bytes available for root */
+ if (total_number_of_free_bytes != NULL) {
+ if (isreadonly) {
+ *total_number_of_free_bytes = 0;
+ }
+ else {
+ *total_number_of_free_bytes = block_size * (guint64)fsstat.f_bfree;
+ }
+ }
+
+ return(TRUE);
+}
+#else
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
+{
+ if (free_bytes_avail != NULL) {
+ *free_bytes_avail = (guint64) -1;
+ }
+
+ if (total_number_of_bytes != NULL) {
+ *total_number_of_bytes = (guint64) -1;
+ }
+
+ if (total_number_of_free_bytes != NULL) {
+ *total_number_of_free_bytes = (guint64) -1;
+ }
+
+ return(TRUE);
+}
+#endif
+
+/*
+ * General Unix support
+ */
+typedef struct {
+ guint32 drive_type;
+#if __linux__
+ const long fstypeid;
+#endif
+ const gchar* fstype;
+} _wapi_drive_type;
+
+static _wapi_drive_type _wapi_drive_types[] = {
+#if PLATFORM_MACOSX
+ { DRIVE_REMOTE, "afp" },
+ { DRIVE_REMOTE, "autofs" },
+ { DRIVE_CDROM, "cddafs" },
+ { DRIVE_CDROM, "cd9660" },
+ { DRIVE_RAMDISK, "devfs" },
+ { DRIVE_FIXED, "exfat" },
+ { DRIVE_RAMDISK, "fdesc" },
+ { DRIVE_REMOTE, "ftp" },
+ { DRIVE_FIXED, "hfs" },
+ { DRIVE_FIXED, "msdos" },
+ { DRIVE_REMOTE, "nfs" },
+ { DRIVE_FIXED, "ntfs" },
+ { DRIVE_REMOTE, "smbfs" },
+ { DRIVE_FIXED, "udf" },
+ { DRIVE_REMOTE, "webdav" },
+ { DRIVE_UNKNOWN, NULL }
+#elif __linux__
+ { DRIVE_FIXED, ADFS_SUPER_MAGIC, "adfs"},
+ { DRIVE_FIXED, AFFS_SUPER_MAGIC, "affs"},
+ { DRIVE_REMOTE, AFS_SUPER_MAGIC, "afs"},
+ { DRIVE_RAMDISK, AUTOFS_SUPER_MAGIC, "autofs"},
+ { DRIVE_RAMDISK, AUTOFS_SBI_MAGIC, "autofs4"},
+ { DRIVE_REMOTE, CODA_SUPER_MAGIC, "coda" },
+ { DRIVE_RAMDISK, CRAMFS_MAGIC, "cramfs"},
+ { DRIVE_RAMDISK, CRAMFS_MAGIC_WEND, "cramfs"},
+ { DRIVE_REMOTE, CIFS_MAGIC_NUMBER, "cifs"},
+ { DRIVE_RAMDISK, DEBUGFS_MAGIC, "debugfs"},
+ { DRIVE_RAMDISK, SYSFS_MAGIC, "sysfs"},
+ { DRIVE_RAMDISK, SECURITYFS_MAGIC, "securityfs"},
+ { DRIVE_RAMDISK, SELINUX_MAGIC, "selinuxfs"},
+ { DRIVE_RAMDISK, RAMFS_MAGIC, "ramfs"},
+ { DRIVE_FIXED, SQUASHFS_MAGIC, "squashfs"},
+ { DRIVE_FIXED, EFS_SUPER_MAGIC, "efs"},
+ { DRIVE_FIXED, EXT2_SUPER_MAGIC, "ext"},
+ { DRIVE_FIXED, EXT3_SUPER_MAGIC, "ext"},
+ { DRIVE_FIXED, EXT4_SUPER_MAGIC, "ext"},
+ { DRIVE_REMOTE, XENFS_SUPER_MAGIC, "xenfs"},
+ { DRIVE_FIXED, BTRFS_SUPER_MAGIC, "btrfs"},
+ { DRIVE_FIXED, HFS_SUPER_MAGIC, "hfs"},
+ { DRIVE_FIXED, HFSPLUS_SUPER_MAGIC, "hfsplus"},
+ { DRIVE_FIXED, HPFS_SUPER_MAGIC, "hpfs"},
+ { DRIVE_RAMDISK, HUGETLBFS_MAGIC, "hugetlbfs"},
+ { DRIVE_CDROM, ISOFS_SUPER_MAGIC, "iso"},
+ { DRIVE_FIXED, JFFS2_SUPER_MAGIC, "jffs2"},
+ { DRIVE_RAMDISK, ANON_INODE_FS_MAGIC, "anon_inode"},
+ { DRIVE_FIXED, JFS_SUPER_MAGIC, "jfs"},
+ { DRIVE_FIXED, MINIX_SUPER_MAGIC, "minix"},
+ { DRIVE_FIXED, MINIX_SUPER_MAGIC2, "minix v2"},
+ { DRIVE_FIXED, MINIX2_SUPER_MAGIC, "minix2"},
+ { DRIVE_FIXED, MINIX2_SUPER_MAGIC2, "minix2 v2"},
+ { DRIVE_FIXED, MINIX3_SUPER_MAGIC, "minix3"},
+ { DRIVE_FIXED, MSDOS_SUPER_MAGIC, "msdos"},
+ { DRIVE_REMOTE, NCP_SUPER_MAGIC, "ncp"},
+ { DRIVE_REMOTE, NFS_SUPER_MAGIC, "nfs"},
+ { DRIVE_FIXED, NTFS_SB_MAGIC, "ntfs"},
+ { DRIVE_RAMDISK, OPENPROM_SUPER_MAGIC, "openpromfs"},
+ { DRIVE_RAMDISK, PROC_SUPER_MAGIC, "proc"},
+ { DRIVE_FIXED, QNX4_SUPER_MAGIC, "qnx4"},
+ { DRIVE_FIXED, REISERFS_SUPER_MAGIC, "reiserfs"},
+ { DRIVE_RAMDISK, ROMFS_MAGIC, "romfs"},
+ { DRIVE_REMOTE, SMB_SUPER_MAGIC, "samba"},
+ { DRIVE_RAMDISK, CGROUP_SUPER_MAGIC, "cgroupfs"},
+ { DRIVE_RAMDISK, FUTEXFS_SUPER_MAGIC, "futexfs"},
+ { DRIVE_FIXED, SYSV2_SUPER_MAGIC, "sysv2"},
+ { DRIVE_FIXED, SYSV4_SUPER_MAGIC, "sysv4"},
+ { DRIVE_RAMDISK, TMPFS_MAGIC, "tmpfs"},
+ { DRIVE_RAMDISK, DEVPTS_SUPER_MAGIC, "devpts"},
+ { DRIVE_CDROM, UDF_SUPER_MAGIC, "udf"},
+ { DRIVE_FIXED, UFS_MAGIC, "ufs"},
+ { DRIVE_FIXED, UFS_MAGIC_BW, "ufs"},
+ { DRIVE_FIXED, UFS2_MAGIC, "ufs2"},
+ { DRIVE_FIXED, UFS_CIGAM, "ufs"},
+ { DRIVE_RAMDISK, USBDEVICE_SUPER_MAGIC, "usbdev"},
+ { DRIVE_FIXED, XENIX_SUPER_MAGIC, "xenix"},
+ { DRIVE_FIXED, XFS_SB_MAGIC, "xfs"},
+ { DRIVE_RAMDISK, FUSE_SUPER_MAGIC, "fuse"},
+ { DRIVE_FIXED, V9FS_MAGIC, "9p"},
+ { DRIVE_REMOTE, CEPH_SUPER_MAGIC, "ceph"},
+ { DRIVE_RAMDISK, CONFIGFS_MAGIC, "configfs"},
+ { DRIVE_RAMDISK, ECRYPTFS_SUPER_MAGIC, "eCryptfs"},
+ { DRIVE_FIXED, EXOFS_SUPER_MAGIC, "exofs"},
+ { DRIVE_FIXED, VXFS_SUPER_MAGIC, "vxfs"},
+ { DRIVE_FIXED, VXFS_OLT_MAGIC, "vxfs_olt"},
+ { DRIVE_REMOTE, GFS2_MAGIC, "gfs2"},
+ { DRIVE_FIXED, LOGFS_MAGIC_U32, "logfs"},
+ { DRIVE_FIXED, OCFS2_SUPER_MAGIC, "ocfs2"},
+ { DRIVE_FIXED, OMFS_MAGIC, "omfs"},
+ { DRIVE_FIXED, UBIFS_SUPER_MAGIC, "ubifs"},
+ { DRIVE_UNKNOWN, 0, NULL}
+#else
+ { DRIVE_RAMDISK, "ramfs" },
+ { DRIVE_RAMDISK, "tmpfs" },
+ { DRIVE_RAMDISK, "proc" },
+ { DRIVE_RAMDISK, "sysfs" },
+ { DRIVE_RAMDISK, "debugfs" },
+ { DRIVE_RAMDISK, "devpts" },
+ { DRIVE_RAMDISK, "securityfs" },
+ { DRIVE_CDROM, "iso9660" },
+ { DRIVE_FIXED, "ext2" },
+ { DRIVE_FIXED, "ext3" },
+ { DRIVE_FIXED, "ext4" },
+ { DRIVE_FIXED, "sysv" },
+ { DRIVE_FIXED, "reiserfs" },
+ { DRIVE_FIXED, "ufs" },
+ { DRIVE_FIXED, "vfat" },
+ { DRIVE_FIXED, "msdos" },
+ { DRIVE_FIXED, "udf" },
+ { DRIVE_FIXED, "hfs" },
+ { DRIVE_FIXED, "hpfs" },
+ { DRIVE_FIXED, "qnx4" },
+ { DRIVE_FIXED, "ntfs" },
+ { DRIVE_FIXED, "ntfs-3g" },
+ { DRIVE_REMOTE, "smbfs" },
+ { DRIVE_REMOTE, "fuse" },
+ { DRIVE_REMOTE, "nfs" },
+ { DRIVE_REMOTE, "nfs4" },
+ { DRIVE_REMOTE, "cifs" },
+ { DRIVE_REMOTE, "ncpfs" },
+ { DRIVE_REMOTE, "coda" },
+ { DRIVE_REMOTE, "afs" },
+ { DRIVE_UNKNOWN, NULL }
+#endif
+};
+
+#if __linux__
+static guint32 _wapi_get_drive_type(long f_type)
+{
+ _wapi_drive_type *current;
+
+ current = &_wapi_drive_types[0];
+ while (current->drive_type != DRIVE_UNKNOWN) {
+ if (current->fstypeid == f_type)
+ return current->drive_type;
+ current++;
+ }
+
+ return DRIVE_UNKNOWN;
+}
+#else
+static guint32 _wapi_get_drive_type(const gchar* fstype)
+{
+ _wapi_drive_type *current;
+
+ current = &_wapi_drive_types[0];
+ while (current->drive_type != DRIVE_UNKNOWN) {
+ if (strcmp (current->fstype, fstype) == 0)
+ break;
+
+ current++;
+ }
+
+ return current->drive_type;
+}
+#endif
+
+#if defined (PLATFORM_MACOSX) || defined (__linux__)
+static guint32
+GetDriveTypeFromPath (const gchar *utf8_root_path_name)
+{
+ struct statfs buf;
+
+ if (statfs (utf8_root_path_name, &buf) == -1)
+ return DRIVE_UNKNOWN;
+#if PLATFORM_MACOSX
+ return _wapi_get_drive_type (buf.f_fstypename);
+#else
+ return _wapi_get_drive_type (buf.f_type);
+#endif
+}
+#else
+static guint32
+GetDriveTypeFromPath (const gchar *utf8_root_path_name)
+{
+ guint32 drive_type;
+ FILE *fp;
+ gchar buffer [512];
+ gchar **splitted;
+
+ fp = fopen ("/etc/mtab", "rt");
+ if (fp == NULL) {
+ fp = fopen ("/etc/mnttab", "rt");
+ if (fp == NULL)
+ return(DRIVE_UNKNOWN);
+ }
+
+ drive_type = DRIVE_NO_ROOT_DIR;
+ while (fgets (buffer, 512, fp) != NULL) {
+ splitted = g_strsplit (buffer, " ", 0);
+ if (!*splitted || !*(splitted + 1) || !*(splitted + 2)) {
+ g_strfreev (splitted);
+ continue;
+ }
+
+ /* compare given root_path_name with the one from mtab,
+ if length of utf8_root_path_name is zero it must be the root dir */
+ if (strcmp (*(splitted + 1), utf8_root_path_name) == 0 ||
+ (strcmp (*(splitted + 1), "/") == 0 && strlen (utf8_root_path_name) == 0)) {
+ drive_type = _wapi_get_drive_type (*(splitted + 2));
+ /* it is possible this path might be mounted again with
+ a known type...keep looking */
+ if (drive_type != DRIVE_UNKNOWN) {
+ g_strfreev (splitted);
+ break;
+ }
+ }
+
+ g_strfreev (splitted);
+ }
+
+ fclose (fp);
+ return drive_type;
+}
+#endif
+
+guint32
+mono_w32file_get_drive_type(const gunichar2 *root_path_name)
+{
+ gchar *utf8_root_path_name;
+ guint32 drive_type;
+
+ if (root_path_name == NULL) {
+ utf8_root_path_name = g_strdup (g_get_current_dir());
+ if (utf8_root_path_name == NULL) {
+ return(DRIVE_NO_ROOT_DIR);
+ }
+ }
+ else {
+ utf8_root_path_name = mono_unicode_to_external (root_path_name);
+ if (utf8_root_path_name == NULL) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
+ return(DRIVE_NO_ROOT_DIR);
+ }
+
+ /* strip trailing slash for compare below */
+ if (g_str_has_suffix(utf8_root_path_name, "/") && utf8_root_path_name [1] != 0) {
+ utf8_root_path_name[strlen(utf8_root_path_name) - 1] = 0;
+ }
+ }
+ drive_type = GetDriveTypeFromPath (utf8_root_path_name);
+ g_free (utf8_root_path_name);
+
+ return (drive_type);
+}
+
+#if defined (PLATFORM_MACOSX) || defined (__linux__) || defined(PLATFORM_BSD) || defined(__native_client__) || defined(__FreeBSD_kernel__)
+static gchar*
+get_fstypename (gchar *utfpath)
+{
+#if defined (PLATFORM_MACOSX) || defined (__linux__)
+ struct statfs stat;
+#if __linux__
+ _wapi_drive_type *current;
+#endif
+ if (statfs (utfpath, &stat) == -1)
+ return NULL;
+#if PLATFORM_MACOSX
+ return g_strdup (stat.f_fstypename);
+#else
+ current = &_wapi_drive_types[0];
+ while (current->drive_type != DRIVE_UNKNOWN) {
+ if (stat.f_type == current->fstypeid)
+ return g_strdup (current->fstype);
+ current++;
+ }
+ return NULL;
+#endif
+#else
+ return NULL;
+#endif
+}
+
+/* Linux has struct statfs which has a different layout */
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
+{
+ gchar *utfpath;
+ gchar *fstypename;
+ gboolean status = FALSE;
+ glong len;
+
+ // We only support getting the file system type
+ if (fsbuffer == NULL)
+ return 0;
+
+ utfpath = mono_unicode_to_external (path);
+ if ((fstypename = get_fstypename (utfpath)) != NULL){
+ gunichar2 *ret = g_utf8_to_utf16 (fstypename, -1, NULL, &len, NULL);
+ if (ret != NULL && len < fsbuffersize){
+ memcpy (fsbuffer, ret, len * sizeof (gunichar2));
+ fsbuffer [len] = 0;
+ status = TRUE;
+ }
+ if (ret != NULL)
+ g_free (ret);
+ g_free (fstypename);
+ }
+ g_free (utfpath);
+ return status;
+}
+#endif
+
+static gboolean
+LockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
+{
+ MonoW32HandleFile *file_handle;
+ off_t offset, length;
+
+ if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
+ g_warning ("%s: error looking up file handle %p", __func__, handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+ offset = ((gint64)offset_high << 32) | offset_low;
+ length = ((gint64)length_high << 32) | length_low;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
+#else
+ if (offset_high > 0 || length_high > 0) {
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ offset = offset_low;
+ length = length_low;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Locking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
+#endif
+
+ return _wapi_lock_file_region (GPOINTER_TO_UINT(handle), offset, length);
+}
+
+static gboolean
+UnlockFile (gpointer handle, guint32 offset_low, guint32 offset_high, guint32 length_low, guint32 length_high)
+{
+ MonoW32HandleFile *file_handle;
+ off_t offset, length;
+
+ if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_FILE, (gpointer *)&file_handle)) {
+ g_warning ("%s: error looking up file handle %p", __func__, handle);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+
+ if (!(file_handle->fileaccess & GENERIC_READ) && !(file_handle->fileaccess & GENERIC_WRITE) && !(file_handle->fileaccess & GENERIC_ALL)) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: handle %p doesn't have GENERIC_READ or GENERIC_WRITE access: %u", __func__, handle, file_handle->fileaccess);
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+#ifdef HAVE_LARGE_FILE_SUPPORT
+ offset = ((gint64)offset_high << 32) | offset_low;
+ length = ((gint64)length_high << 32) | length_low;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %lld, length %lld", __func__, handle, offset, length);
+#else
+ offset = offset_low;
+ length = length_low;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Unlocking handle %p, offset %ld, length %ld", __func__, handle, offset, length);
+#endif
+
+ return _wapi_unlock_file_region (GPOINTER_TO_UINT(handle), offset, length);
+}
+
+void
+mono_w32file_init (void)
+{
+ mono_os_mutex_init (&stdhandle_mutex);
+ mono_os_mutex_init (&file_share_mutex);
+
+ mono_w32handle_register_ops (MONO_W32HANDLE_FILE, &_wapi_file_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_CONSOLE, &_wapi_console_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_FIND, &_wapi_find_ops);
+ mono_w32handle_register_ops (MONO_W32HANDLE_PIPE, &_wapi_pipe_ops);
+
+/* mono_w32handle_register_capabilities (MONO_W32HANDLE_FILE, */
+/* MONO_W32HANDLE_CAP_WAIT); */
+/* mono_w32handle_register_capabilities (MONO_W32HANDLE_CONSOLE, */
+/* MONO_W32HANDLE_CAP_WAIT); */
+
+ if (g_getenv ("MONO_STRICT_IO_EMULATION"))
+ lock_while_writing = TRUE;
+}
+
+void
+mono_w32file_cleanup (void)
+{
+ mono_os_mutex_destroy (&file_share_mutex);
+
+ if (file_share_table)
+ g_hash_table_destroy (file_share_table);
+}
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = MoveFile (path, dest);
+ if (!result)
+ *error = mono_w32error_get_last ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = CopyFile (path, dest, !overwrite);
+ if (!result)
+ *error = mono_w32error_get_last ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
+ if (!result)
+ *error = mono_w32error_get_last ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gint64
+mono_w32file_get_file_size (gpointer handle, gint32 *error)
+{
+ gint64 length;
+ guint32 length_hi;
+
+ MONO_ENTER_GC_SAFE;
+
+ length = GetFileSize (handle, &length_hi);
+ if(length==INVALID_FILE_SIZE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+
+ return length | ((gint64)length_hi << 32);
+}
+
+gboolean
+mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+ if (!result)
+ *error = mono_w32error_get_last ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+ if (!result)
+ *error = mono_w32error_get_last ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gpointer
+mono_w32file_get_console_input (void)
+{
+ gpointer handle;
+
+ MONO_ENTER_GC_SAFE;
+ handle = mono_w32file_get_std_handle (STD_INPUT_HANDLE);
+ MONO_EXIT_GC_SAFE;
+
+ return handle;
+}
+
+gpointer
+mono_w32file_get_console_output (void)
+{
+ gpointer handle;
+
+ MONO_ENTER_GC_SAFE;
+ handle = mono_w32file_get_std_handle (STD_OUTPUT_HANDLE);
+ MONO_EXIT_GC_SAFE;
+
+ return handle;
+}
+
+gpointer
+mono_w32file_get_console_error (void)
+{
+ gpointer handle;
+
+ MONO_ENTER_GC_SAFE;
+ handle = mono_w32file_get_std_handle (STD_ERROR_HANDLE);
+ MONO_EXIT_GC_SAFE;
+
+ return handle;
+}
--- /dev/null
+/*
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#ifndef _MONO_METADATA_W32FILE_WIN32_INTERNALS_H_
+#define _MONO_METADATA_W32FILE_WIN32_INTERNALS_H_
+
+#include <config.h>
+#include <glib.h>
+
+#ifdef HOST_WIN32
+#include "mono/metadata/w32file.h"
+#include "mono/metadata/w32file-internals.h"
+#endif /* HOST_WIN32 */
+#endif /* _MONO_METADATA_W32FILE_WIN32_INTERNALS_H_ */
--- /dev/null
+/*
+ * w32file-win32-uwp.c: UWP w32file support for Mono.
+ *
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+*/
+#include <config.h>
+#include <glib.h>
+#include "mono/utils/mono-compiler.h"
+
+#if G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT)
+#include <windows.h>
+#include "mono/metadata/w32file-win32-internals.h"
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
+{
+ gboolean result = FALSE;
+ MONO_ENTER_GC_SAFE;
+
+ result = MoveFileEx (path, dest, MOVEFILE_COPY_ALLOWED);
+ if (result == FALSE) {
+ *error=GetLastError ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return result;
+}
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName,
+ gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
+{
+ gboolean result = FALSE;
+ MONO_ENTER_GC_SAFE;
+
+ result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
+ if (result == FALSE) {
+ *error=GetLastError ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return result;
+}
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
+{
+ gboolean result = FALSE;
+ COPYFILE2_EXTENDED_PARAMETERS copy_param = {0};
+
+ copy_param.dwSize = sizeof (COPYFILE2_EXTENDED_PARAMETERS);
+ copy_param.dwCopyFlags = (!overwrite) ? COPY_FILE_FAIL_IF_EXISTS : 0;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = SUCCEEDED (CopyFile2 (path, dest, ©_param));
+ if (result == FALSE) {
+ *error=GetLastError ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return result;
+}
+
+gint64
+mono_w32file_get_file_size (HANDLE handle, gint32 *error)
+{
+ LARGE_INTEGER length;
+
+ MONO_ENTER_GC_SAFE;
+
+ if (!GetFileSizeEx (handle, &length)) {
+ *error=GetLastError ();
+ length.QuadPart = INVALID_FILE_SIZE;
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return length.QuadPart;
+}
+
+gboolean
+mono_w32file_lock (HANDLE handle, gint64 position, gint64 length, gint32 *error)
+{
+ gboolean result = FALSE;
+ MONO_ENTER_GC_SAFE;
+
+ result = LockFile (handle, position & 0xFFFFFFFF, position >> 32,
+ length & 0xFFFFFFFF, length >> 32);
+
+ if (result == FALSE) {
+ *error = GetLastError ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return result;
+}
+
+gboolean
+mono_w32file_unlock (HANDLE handle, gint64 position, gint64 length, gint32 *error)
+{
+ gboolean result = FALSE;
+ MONO_ENTER_GC_SAFE;
+
+ result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32,
+ length & 0xFFFFFFFF, length >> 32);
+
+ if (result == FALSE) {
+ *error = GetLastError ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return result;
+}
+
+HANDLE
+mono_w32file_get_console_output (void)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetStdHandle (STD_OUTPUT_HANDLE)");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_OUTPUT_HANDLE)");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return INVALID_HANDLE_VALUE;
+}
+
+HANDLE
+mono_w32file_get_console_input (void)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetStdHandle (STD_INPUT_HANDLE)");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_INPUT_HANDLE)");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return INVALID_HANDLE_VALUE;
+}
+
+HANDLE
+mono_w32file_get_console_error (void)
+{
+ MonoError mono_error;
+ mono_error_init (&mono_error);
+
+ g_unsupported_api ("GetStdHandle (STD_ERROR_HANDLE)");
+
+ mono_error_set_not_supported (&mono_error, G_UNSUPPORTED_API, "GetStdHandle (STD_ERROR_HANDLE)");
+ mono_error_set_pending_exception (&mono_error);
+
+ SetLastError (ERROR_NOT_SUPPORTED);
+
+ return INVALID_HANDLE_VALUE;
+}
+
+#else /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
+
+MONO_EMPTY_SOURCE_FILE (file_io_windows_uwp);
+#endif /* G_HAVE_API_SUPPORT(HAVE_UWP_WINAPI_SUPPORT) */
--- /dev/null
+/*
+ * w32file-win32.c: Windows File IO internal calls.
+ *
+ * Copyright 2016 Microsoft
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+#include <config.h>
+#include <glib.h>
+
+#include <winsock2.h>
+#include <windows.h>
+#include "mono/metadata/w32file-win32-internals.h"
+
+void
+mono_w32file_init (void)
+{
+}
+
+void
+mono_w32file_cleanup (void)
+{
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
+{
+ return (gunichar2) ':'; /* colon */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
+{
+ return (gunichar2) '\\'; /* backslash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
+{
+ return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_PathSeparator ()
+{
+ return (gunichar2) ';'; /* semicolon */
+}
+
+void ves_icall_System_IO_MonoIO_DumpHandles (void)
+{
+ return;
+}
+
+gpointer
+mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
+{
+ return CreateFile (name, fileaccess, sharemode, NULL, createmode, attrs, NULL);
+}
+
+gboolean
+mono_w32file_close (gpointer handle)
+{
+ return CloseHandle (handle);
+}
+
+gboolean
+mono_w32file_delete (const gunichar2 *name)
+{
+ return DeleteFile (name);
+}
+
+gboolean
+mono_w32file_read(gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread)
+{
+ return ReadFile (handle, buffer, numbytes, bytesread, NULL);
+}
+
+gboolean
+mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten)
+{
+ return WriteFile (handle, buffer, numbytes, byteswritten, NULL);
+}
+
+gboolean
+mono_w32file_flush (gpointer handle)
+{
+ return FlushFileBuffers (handle);
+}
+
+gboolean
+mono_w32file_truncate (gpointer handle)
+{
+ return SetEndOfFile (handle);
+}
+
+guint32
+mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method)
+{
+ return SetFilePointer (handle, movedistance, highmovedistance, method);
+}
+
+gint
+mono_w32file_get_type (gpointer handle)
+{
+ return GetFileType (handle);
+}
+
+gboolean
+mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time)
+{
+ return GetFileTime (handle, create_time, access_time, write_time);
+}
+
+gboolean
+mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time)
+{
+ return SetFileTime (handle, create_time, access_time, write_time);
+}
+
+gboolean
+mono_w32file_filetime_to_systemtime (const FILETIME *file_time, SYSTEMTIME *system_time)
+{
+ return FileTimeToSystemTime (file_time, system_time);
+}
+
+gpointer
+mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data)
+{
+ return FindFirstFile (pattern, find_data);
+}
+
+gboolean
+mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data)
+{
+ return FindNextFile (handle, find_data);
+}
+
+gboolean
+mono_w32file_find_close (gpointer handle)
+{
+ return FindClose (handle);
+}
+
+gboolean
+mono_w32file_create_directory (const gunichar2 *name)
+{
+ return CreateDirectory (name, NULL);
+}
+
+gboolean
+mono_w32file_remove_directory (const gunichar2 *name)
+{
+ return RemoveDirectory (name);
+}
+
+guint32
+mono_w32file_get_attributes (const gunichar2 *name)
+{
+ return GetFileAttributes (name);
+}
+
+gboolean
+mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat)
+{
+ gboolean result;
+ WIN32_FILE_ATTRIBUTE_DATA data;
+
+ result = GetFileAttributesEx (name, GetFileExInfoStandard, &data);
+ if (result) {
+ stat->attributes = data.dwFileAttributes;
+ stat->creation_time = (gint64) ((((guint64) data.ftCreationTime.dwHighDateTime) << 32) + data.ftCreationTime.dwLowDateTime);
+ stat->last_access_time = (gint64) ((((guint64) data.ftLastAccessTime.dwHighDateTime) << 32) + data.ftLastAccessTime.dwLowDateTime);
+ stat->last_write_time = (gint64) ((((guint64) data.ftLastWriteTime.dwHighDateTime) << 32) + data.ftLastWriteTime.dwLowDateTime);
+ stat->length = ((gint64)data.nFileSizeHigh << 32) | data.nFileSizeLow;
+ }
+
+ return result;
+}
+
+gboolean
+mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs)
+{
+ return SetFileAttributes (name, attrs);
+}
+
+guint32
+mono_w32file_get_cwd (guint32 length, gunichar2 *buffer)
+{
+ return GetCurrentDirectory (length, buffer);
+}
+
+gboolean
+mono_w32file_set_cwd (const gunichar2 *path)
+{
+ return SetCurrentDirectory (path);
+}
+
+gboolean
+mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size)
+{
+ SECURITY_ATTRIBUTES attr;
+ attr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ attr.bInheritHandle = TRUE;
+ attr.lpSecurityDescriptor = NULL;
+ return CreatePipe (readpipe, writepipe, &attr, size);
+}
+
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes)
+{
+ gboolean result;
+ ULARGE_INTEGER *wapi_free_bytes_avail;
+ ULARGE_INTEGER *wapi_total_number_of_bytes;
+ ULARGE_INTEGER *wapi_total_number_of_free_bytes;
+
+ result = GetDiskFreeSpaceEx (path_name, wapi_free_bytes_avail, wapi_total_number_of_bytes, wapi_total_number_of_free_bytes);
+ if (result) {
+ if (free_bytes_avail)
+ *free_bytes_avail = wapi_free_bytes_avail->QuadPart;
+ if (total_number_of_bytes)
+ *total_number_of_bytes = wapi_total_number_of_bytes->QuadPart;
+ if (total_number_of_free_bytes)
+ *total_number_of_free_bytes = wapi_total_number_of_free_bytes->QuadPart;
+ }
+
+ return result;
+}
+
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize)
+{
+ return GetVolumeInformation (path, volumename, volumesize, outserial, maxcomp, fsflags, fsbuffer, fsbuffersize);
+}
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = MoveFile (path, dest);
+ if (!result)
+ *error = GetLastError ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = ReplaceFile (destinationFileName, sourceFileName, destinationBackupFileName, flags, NULL, NULL);
+ if (!result)
+ *error = GetLastError ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = CopyFile (path, dest, !overwrite);
+ if (!result)
+ *error = GetLastError ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = LockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+ if (!result)
+ *error = GetLastError ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+gboolean
+mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error)
+{
+ gboolean result;
+
+ MONO_ENTER_GC_SAFE;
+
+ result = UnlockFile (handle, position & 0xFFFFFFFF, position >> 32, length & 0xFFFFFFFF, length >> 32);
+ if (!result)
+ *error = GetLastError ();
+
+ MONO_EXIT_GC_SAFE;
+
+ return result;
+}
+
+HANDLE
+mono_w32file_get_console_input (void)
+{
+ return GetStdHandle (STD_INPUT_HANDLE);
+}
+
+HANDLE
+mono_w32file_get_console_output (void)
+{
+ return GetStdHandle (STD_OUTPUT_HANDLE);
+}
+
+HANDLE
+mono_w32file_get_console_error (void)
+{
+ return GetStdHandle (STD_ERROR_HANDLE);
+}
+
+gint64
+mono_w32file_get_file_size (gpointer handle, gint32 *error)
+{
+ gint64 length;
+ guint32 length_hi;
+
+ MONO_ENTER_GC_SAFE;
+
+ length = GetFileSize (handle, &length_hi);
+ if(length==INVALID_FILE_SIZE) {
+ *error=GetLastError ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+
+ return length | ((gint64)length_hi << 32);
+}
+
+guint32
+mono_w32file_get_drive_type (const gunichar2 *root_path_name)
+{
+ return GetDriveType (root_path_name);
+}
+
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf)
+{
+ return GetLogicalDriveStrings (len, buf);
+}
+
+#endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
--- /dev/null
+/*
+ * w32file.c: File IO internal calls
+ *
+ * Author:
+ * Dick Porter (dick@ximian.com)
+ * Gonzalo Paniagua Javier (gonzalo@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <mono/metadata/object.h>
+#include <mono/metadata/w32file.h>
+#include <mono/metadata/w32error.h>
+#include <mono/metadata/w32file-internals.h>
+#include <mono/metadata/exception.h>
+#include <mono/metadata/appdomain.h>
+#include <mono/metadata/marshal.h>
+#include <mono/utils/strenc.h>
+#include <utils/mono-io-portability.h>
+#include <mono/metadata/w32handle.h>
+#include <mono/utils/w32api.h>
+
+#undef DEBUG
+
+/* conversion functions */
+
+static guint32 convert_mode(MonoFileMode mono_mode)
+{
+ guint32 mode;
+
+ switch(mono_mode) {
+ case FileMode_CreateNew:
+ mode=CREATE_NEW;
+ break;
+ case FileMode_Create:
+ mode=CREATE_ALWAYS;
+ break;
+ case FileMode_Open:
+ mode=OPEN_EXISTING;
+ break;
+ case FileMode_OpenOrCreate:
+ mode=OPEN_ALWAYS;
+ break;
+ case FileMode_Truncate:
+ mode=TRUNCATE_EXISTING;
+ break;
+ case FileMode_Append:
+ mode=OPEN_ALWAYS;
+ break;
+ default:
+ g_warning("System.IO.FileMode has unknown value 0x%x",
+ mono_mode);
+ /* Safe fallback */
+ mode=OPEN_EXISTING;
+ }
+
+ return(mode);
+}
+
+static guint32 convert_access(MonoFileAccess mono_access)
+{
+ guint32 access;
+
+ switch(mono_access) {
+ case FileAccess_Read:
+ access=GENERIC_READ;
+ break;
+ case FileAccess_Write:
+ access=GENERIC_WRITE;
+ break;
+ case FileAccess_ReadWrite:
+ access=GENERIC_READ|GENERIC_WRITE;
+ break;
+ default:
+ g_warning("System.IO.FileAccess has unknown value 0x%x",
+ mono_access);
+ /* Safe fallback */
+ access=GENERIC_READ;
+ }
+
+ return(access);
+}
+
+static guint32 convert_share(MonoFileShare mono_share)
+{
+ guint32 share = 0;
+
+ if (mono_share & FileShare_Read) {
+ share |= FILE_SHARE_READ;
+ }
+ if (mono_share & FileShare_Write) {
+ share |= FILE_SHARE_WRITE;
+ }
+ if (mono_share & FileShare_Delete) {
+ share |= FILE_SHARE_DELETE;
+ }
+
+ if (mono_share & ~(FileShare_Read|FileShare_Write|FileShare_Delete)) {
+ g_warning("System.IO.FileShare has unknown value 0x%x",
+ mono_share);
+ /* Safe fallback */
+ share=0;
+ }
+
+ return(share);
+}
+
+#if 0
+static guint32 convert_stdhandle(guint32 fd)
+{
+ guint32 stdhandle;
+
+ switch(fd) {
+ case 0:
+ stdhandle=STD_INPUT_HANDLE;
+ break;
+ case 1:
+ stdhandle=STD_OUTPUT_HANDLE;
+ break;
+ case 2:
+ stdhandle=STD_ERROR_HANDLE;
+ break;
+ default:
+ g_warning("unknown standard file descriptor %d", fd);
+ stdhandle=STD_INPUT_HANDLE;
+ }
+
+ return(stdhandle);
+}
+#endif
+
+static guint32 convert_seekorigin(MonoSeekOrigin origin)
+{
+ guint32 w32origin;
+
+ switch(origin) {
+ case SeekOrigin_Begin:
+ w32origin=FILE_BEGIN;
+ break;
+ case SeekOrigin_Current:
+ w32origin=FILE_CURRENT;
+ break;
+ case SeekOrigin_End:
+ w32origin=FILE_END;
+ break;
+ default:
+ g_warning("System.IO.SeekOrigin has unknown value 0x%x",
+ origin);
+ /* Safe fallback */
+ w32origin=FILE_CURRENT;
+ }
+
+ return(w32origin);
+}
+
+static gint64 convert_filetime (const FILETIME *filetime)
+{
+ return (gint64) ((((guint64) filetime->dwHighDateTime) << 32) + filetime->dwLowDateTime);
+}
+
+/* Managed file attributes have nearly but not quite the same values
+ * as the w32 equivalents.
+ */
+static guint32 convert_attrs(MonoFileAttributes attrs)
+{
+ if(attrs & FileAttributes_Encrypted) {
+ attrs = (MonoFileAttributes)(attrs | FILE_ATTRIBUTE_ENCRYPTED);
+ }
+
+ return(attrs);
+}
+
+/*
+ * On Win32, mono_w32file_get_attributes|_ex () seems to try opening the file,
+ * which might lead to sharing violation errors, whereas mono_w32file_find_first
+ * always succeeds. These 2 wrappers resort to mono_w32file_find_first if
+ * mono_w32file_get_attributes|_ex () has failed.
+ */
+static guint32
+get_file_attributes (const gunichar2 *path)
+{
+ guint32 res;
+ WIN32_FIND_DATA find_data;
+ HANDLE find_handle;
+ gint32 error;
+
+ res = mono_w32file_get_attributes (path);
+ if (res != -1)
+ return res;
+
+ error = mono_w32error_get_last ();
+
+ if (error != ERROR_SHARING_VIOLATION)
+ return res;
+
+ find_handle = mono_w32file_find_first (path, &find_data);
+
+ if (find_handle == INVALID_HANDLE_VALUE)
+ return res;
+
+ mono_w32file_find_close (find_handle);
+
+ return find_data.dwFileAttributes;
+}
+
+static gboolean
+get_file_attributes_ex (const gunichar2 *path, MonoIOStat *stat)
+{
+ gboolean res;
+ WIN32_FIND_DATA find_data;
+ HANDLE find_handle;
+ gint32 error;
+
+ res = mono_w32file_get_attributes_ex (path, stat);
+ if (res)
+ return TRUE;
+
+ error = mono_w32error_get_last ();
+ if (error != ERROR_SHARING_VIOLATION)
+ return FALSE;
+
+ find_handle = mono_w32file_find_first (path, &find_data);
+
+ if (find_handle == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ mono_w32file_find_close (find_handle);
+
+ stat->attributes = find_data.dwFileAttributes;
+ stat->creation_time = convert_filetime (&find_data.ftCreationTime);
+ stat->last_access_time = convert_filetime (&find_data.ftLastAccessTime);
+ stat->last_write_time = convert_filetime (&find_data.ftLastWriteTime);
+ stat->length = ((gint64)find_data.nFileSizeHigh << 32) | find_data.nFileSizeLow;
+ return TRUE;
+}
+
+/* System.IO.MonoIO internal calls */
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_create_directory (mono_string_chars (path));
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_remove_directory (mono_string_chars (path));
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+static gchar *
+get_search_dir (const gunichar2 *pattern)
+{
+ gchar *p;
+ gchar *result;
+
+ p = g_utf16_to_utf8 (pattern, -1, NULL, NULL, NULL);
+ result = g_path_get_dirname (p);
+ g_free (p);
+ return result;
+}
+
+static GPtrArray *
+get_filesystem_entries (const gunichar2 *path,
+ const gunichar2 *path_with_pattern,
+ gint attrs, gint mask,
+ gint32 *error)
+{
+ int i;
+ WIN32_FIND_DATA data;
+ HANDLE find_handle;
+ GPtrArray *names = NULL;
+ gchar *utf8_path = NULL, *utf8_result, *full_name;
+ gint32 attributes;
+
+ mask = convert_attrs ((MonoFileAttributes)mask);
+ attributes = get_file_attributes (path);
+ if (attributes != -1) {
+ if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+ *error = ERROR_INVALID_NAME;
+ goto fail;
+ }
+ } else {
+ *error = mono_w32error_get_last ();
+ goto fail;
+ }
+
+ find_handle = mono_w32file_find_first (path_with_pattern, &data);
+ if (find_handle == INVALID_HANDLE_VALUE) {
+ gint32 find_error = mono_w32error_get_last ();
+
+ if (find_error == ERROR_FILE_NOT_FOUND || find_error == ERROR_NO_MORE_FILES) {
+ /* No files, so just return an empty array */
+ goto fail;
+ }
+
+ *error = find_error;
+ goto fail;
+ }
+
+ utf8_path = get_search_dir (path_with_pattern);
+ names = g_ptr_array_new ();
+
+ do {
+ if ((data.cFileName[0] == '.' && data.cFileName[1] == 0) ||
+ (data.cFileName[0] == '.' && data.cFileName[1] == '.' && data.cFileName[2] == 0)) {
+ continue;
+ }
+
+ if ((data.dwFileAttributes & mask) == attrs) {
+ utf8_result = g_utf16_to_utf8 (data.cFileName, -1, NULL, NULL, NULL);
+ if (utf8_result == NULL) {
+ continue;
+ }
+
+ full_name = g_build_filename (utf8_path, utf8_result, NULL);
+ g_ptr_array_add (names, full_name);
+
+ g_free (utf8_result);
+ }
+ } while(mono_w32file_find_next (find_handle, &data));
+
+ if (mono_w32file_find_close (find_handle) == FALSE) {
+ *error = mono_w32error_get_last ();
+ goto fail;
+ }
+
+ g_free (utf8_path);
+ return names;
+fail:
+ if (names) {
+ for (i = 0; i < names->len; i++)
+ g_free (g_ptr_array_index (names, i));
+ g_ptr_array_free (names, TRUE);
+ }
+ g_free (utf8_path);
+ return FALSE;
+}
+
+
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+ MonoString *path_with_pattern,
+ gint attrs, gint mask,
+ gint32 *ioerror)
+{
+ MonoError error;
+ MonoDomain *domain = mono_domain_get ();
+ MonoArray *result;
+ int i;
+ GPtrArray *names;
+
+ *ioerror = ERROR_SUCCESS;
+
+ MONO_ENTER_GC_SAFE;
+ names = get_filesystem_entries (mono_string_chars (path), mono_string_chars (path_with_pattern), attrs, mask, ioerror);
+ MONO_EXIT_GC_SAFE;
+
+ if (!names) {
+ // If there's no array and no error, then return an empty array.
+ if (*ioerror == ERROR_SUCCESS) {
+ MonoArray *arr = mono_array_new_checked (domain, mono_defaults.string_class, 0, &error);
+ mono_error_set_pending_exception (&error);
+ return arr;
+ }
+ return NULL;
+ }
+
+ result = mono_array_new_checked (domain, mono_defaults.string_class, names->len, &error);
+ if (mono_error_set_pending_exception (&error))
+ goto leave;
+ for (i = 0; i < names->len; i++) {
+ mono_array_setref (result, i, mono_string_new (domain, (const char *)g_ptr_array_index (names, i)));
+ g_free (g_ptr_array_index (names, i));
+ }
+leave:
+ g_ptr_array_free (names, TRUE);
+ return result;
+}
+
+typedef struct {
+ MonoDomain *domain;
+ gchar *utf8_path;
+ HANDLE find_handle;
+} IncrementalFind;
+
+static gboolean
+incremental_find_check_match (IncrementalFind *handle, WIN32_FIND_DATA *data, MonoString **result)
+{
+ gchar *utf8_result;
+ gchar *full_name;
+
+ if ((data->cFileName[0] == '.' && data->cFileName[1] == 0) || (data->cFileName[0] == '.' && data->cFileName[1] == '.' && data->cFileName[2] == 0))
+ return FALSE;
+
+ utf8_result = g_utf16_to_utf8 (data->cFileName, -1, NULL, NULL, NULL);
+ if (utf8_result == NULL)
+ return FALSE;
+
+ full_name = g_build_filename (handle->utf8_path, utf8_result, NULL);
+ g_free (utf8_result);
+ *result = mono_string_new (mono_domain_get (), full_name);
+ g_free (full_name);
+
+ return TRUE;
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
+{
+ HANDLE hnd;
+ WIN32_FIND_DATA data;
+ MonoError error;
+
+ hnd = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
+
+ if (hnd == INVALID_HANDLE_VALUE) {
+ *file_name = NULL;
+ *file_attr = 0;
+ *ioerror = mono_w32error_get_last ();
+ return hnd;
+ }
+
+ mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
+ mono_error_set_pending_exception (&error);
+
+ *file_attr = data.dwFileAttributes;
+ *ioerror = ERROR_SUCCESS;
+
+ return hnd;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_FindNextFile (HANDLE hnd, MonoString **file_name, gint32 *file_attr, gint32 *ioerror)
+{
+ MonoBoolean res;
+ WIN32_FIND_DATA data;
+ MonoError error;
+
+ res = mono_w32file_find_next (hnd, &data);
+
+ if (res == FALSE) {
+ *file_name = NULL;
+ *file_attr = 0;
+ *ioerror = mono_w32error_get_last ();
+ return res;
+ }
+
+ mono_gc_wbarrier_generic_store (file_name, (MonoObject*) mono_string_from_utf16_checked (data.cFileName, &error));
+ mono_error_set_pending_exception (&error);
+
+ *file_attr = data.dwFileAttributes;
+ *ioerror = ERROR_SUCCESS;
+
+ return res;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_FindCloseFile (HANDLE hnd)
+{
+ return mono_w32file_find_close (hnd);
+}
+
+/* FIXME make gc suspendable */
+MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+ MonoString *path_with_pattern,
+ gint32 *result_attr, gint32 *ioerror,
+ gpointer *handle)
+{
+ MonoError error;
+ WIN32_FIND_DATA data;
+ HANDLE find_handle;
+ IncrementalFind *ifh;
+ MonoString *result;
+
+ *ioerror = ERROR_SUCCESS;
+
+ find_handle = mono_w32file_find_first (mono_string_chars (path_with_pattern), &data);
+
+ if (find_handle == INVALID_HANDLE_VALUE) {
+ gint32 find_error = mono_w32error_get_last ();
+ *handle = NULL;
+
+ if (find_error == ERROR_FILE_NOT_FOUND)
+ return NULL;
+
+ *ioerror = find_error;
+ return NULL;
+ }
+
+ ifh = g_new (IncrementalFind, 1);
+ ifh->find_handle = find_handle;
+ ifh->utf8_path = mono_string_to_utf8_checked (path, &error);
+ if (mono_error_set_pending_exception (&error)) {
+ MONO_ENTER_GC_SAFE;
+ mono_w32file_find_close (find_handle);
+ MONO_EXIT_GC_SAFE;
+ g_free (ifh);
+ return NULL;
+ }
+ ifh->domain = mono_domain_get ();
+ *handle = ifh;
+
+ while (incremental_find_check_match (ifh, &data, &result) == 0){
+ if (mono_w32file_find_next (find_handle, &data) == FALSE){
+ int e = mono_w32error_get_last ();
+ if (e != ERROR_NO_MORE_FILES)
+ *ioerror = e;
+ return NULL;
+ }
+ }
+ *result_attr = data.dwFileAttributes;
+
+ return result;
+}
+
+/* FIXME make gc suspendable */
+MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_attr, gint32 *error)
+{
+ IncrementalFind *ifh = (IncrementalFind *)handle;
+ WIN32_FIND_DATA data;
+ MonoString *result;
+
+ *error = ERROR_SUCCESS;
+ do {
+ if (mono_w32file_find_next (ifh->find_handle, &data) == FALSE){
+ int e = mono_w32error_get_last ();
+ if (e != ERROR_NO_MORE_FILES)
+ *error = e;
+ return NULL;
+ }
+ } while (incremental_find_check_match (ifh, &data, &result) == 0);
+
+ *result_attr = data.dwFileAttributes;
+ return result;
+}
+
+int
+ves_icall_System_IO_MonoIO_FindClose (gpointer handle)
+{
+ IncrementalFind *ifh = (IncrementalFind *)handle;
+ gint32 error;
+
+ MONO_ENTER_GC_SAFE;
+ if (mono_w32file_find_close (ifh->find_handle) == FALSE){
+ error = mono_w32error_get_last ();
+ } else
+ error = ERROR_SUCCESS;
+ g_free (ifh->utf8_path);
+ g_free (ifh);
+ MONO_EXIT_GC_SAFE;
+
+ return error;
+}
+
+MonoString *
+ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *io_error)
+{
+ MonoError error;
+ MonoString *result;
+ gunichar2 *buf;
+ int len, res_len;
+
+ len = MAX_PATH + 1; /*FIXME this is too smal under most unix systems.*/
+ buf = g_new (gunichar2, len);
+
+ mono_error_init (&error);
+ *io_error=ERROR_SUCCESS;
+ result = NULL;
+
+ res_len = mono_w32file_get_cwd (len, buf);
+ if (res_len > len) { /*buf is too small.*/
+ int old_res_len = res_len;
+ g_free (buf);
+ buf = g_new (gunichar2, res_len);
+ res_len = mono_w32file_get_cwd (res_len, buf) == old_res_len;
+ }
+
+ if (res_len) {
+ len = 0;
+ while (buf [len])
+ ++ len;
+
+ result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
+ } else {
+ *io_error=mono_w32error_get_last ();
+ }
+
+ g_free (buf);
+ mono_error_set_pending_exception (&error);
+ return result;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
+ gint32 *error)
+{
+ gboolean ret;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_set_cwd (mono_string_chars (path));
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest, gint32 *error)
+{
+ *error=ERROR_SUCCESS;
+ return mono_w32file_move (mono_string_chars (path), mono_string_chars (dest), error);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
+ MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
+ gint32 *error)
+{
+ gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL;
+ guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH;
+
+ if (sourceFileName)
+ utf16_sourceFileName = mono_string_chars (sourceFileName);
+ if (destinationFileName)
+ utf16_destinationFileName = mono_string_chars (destinationFileName);
+ if (destinationBackupFileName)
+ utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName);
+
+ *error = ERROR_SUCCESS;
+ if (ignoreMetadataErrors)
+ replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS;
+
+ /* FIXME: source and destination file names must not be NULL, but apparently they might be! */
+ return mono_w32file_replace (utf16_destinationFileName, utf16_sourceFileName,
+ utf16_destinationBackupFileName, replaceFlags, error);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
+ MonoBoolean overwrite, gint32 *error)
+{
+ *error=ERROR_SUCCESS;
+ return mono_w32file_copy (mono_string_chars (path), mono_string_chars (dest), overwrite, error);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_delete (mono_string_chars (path));
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+gint32
+ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error)
+{
+ gint32 ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=get_file_attributes (mono_string_chars (path));
+
+ /*
+ * The definition of INVALID_FILE_ATTRIBUTES in the cygwin win32
+ * headers is wrong, hence this temporary workaround.
+ * See
+ * http://cygwin.com/ml/cygwin/2003-09/msg01771.html
+ */
+ if (ret==-1) {
+ /* if(ret==INVALID_FILE_ATTRIBUTES) { */
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
+ gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_set_attributes (mono_string_chars (path),
+ convert_attrs ((MonoFileAttributes)attrs));
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+gint32
+ves_icall_System_IO_MonoIO_GetFileType (HANDLE handle, gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_get_type (handle);
+ if(ret==FILE_TYPE_UNKNOWN) {
+ /* Not necessarily an error, but the caller will have
+ * to decide based on the error value.
+ */
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat, gint32 *error)
+{
+ gboolean result;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ result = get_file_attributes_ex (mono_string_chars (path), stat);
+
+ if (!result) {
+ *error=mono_w32error_get_last ();
+ memset (stat, 0, sizeof (MonoIOStat));
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return result;
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
+ gint32 access_mode, gint32 share, gint32 options,
+ gint32 *error)
+{
+ HANDLE ret;
+ int attributes, attrs;
+ gunichar2 *chars;
+ MONO_ENTER_GC_SAFE;
+
+ chars = mono_string_chars (filename);
+ *error=ERROR_SUCCESS;
+
+ if (options != 0){
+ if (options & FileOptions_Encrypted)
+ attributes = FILE_ATTRIBUTE_ENCRYPTED;
+ else
+ attributes = FILE_ATTRIBUTE_NORMAL;
+ if (options & FileOptions_DeleteOnClose)
+ attributes |= FILE_FLAG_DELETE_ON_CLOSE;
+ if (options & FileOptions_SequentialScan)
+ attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+ if (options & FileOptions_RandomAccess)
+ attributes |= FILE_FLAG_RANDOM_ACCESS;
+
+ if (options & FileOptions_Temporary)
+ attributes |= FILE_ATTRIBUTE_TEMPORARY;
+
+ if (options & FileOptions_WriteThrough)
+ attributes |= FILE_FLAG_WRITE_THROUGH;
+ } else
+ attributes = FILE_ATTRIBUTE_NORMAL;
+
+ /* If we're opening a directory we need to set the extra flag
+ */
+ attrs = get_file_attributes (chars);
+ if (attrs != INVALID_FILE_ATTRIBUTES) {
+ if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
+ attributes |= FILE_FLAG_BACKUP_SEMANTICS;
+ }
+ }
+
+ ret=mono_w32file_create (chars, convert_access ((MonoFileAccess)access_mode), convert_share ((MonoFileShare)share), convert_mode ((MonoFileMode)mode), attributes);
+ if(ret==INVALID_HANDLE_VALUE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_Close (HANDLE handle, gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_close (handle);
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+gint32
+ves_icall_System_IO_MonoIO_Read (HANDLE handle, MonoArray *dest,
+ gint32 dest_offset, gint32 count,
+ gint32 *error)
+{
+ guchar *buffer;
+ gboolean result;
+ guint32 n;
+
+ *error=ERROR_SUCCESS;
+
+ MONO_CHECK_ARG_NULL (dest, 0);
+
+ if (dest_offset > mono_array_length (dest) - count) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+ return 0;
+ }
+
+ buffer = mono_array_addr (dest, guchar, dest_offset);
+
+ MONO_ENTER_GC_SAFE;
+ result = mono_w32file_read (handle, buffer, count, &n);
+ MONO_EXIT_GC_SAFE;
+
+ if (!result) {
+ *error=mono_w32error_get_last ();
+ return -1;
+ }
+
+ return (gint32)n;
+}
+
+gint32
+ves_icall_System_IO_MonoIO_Write (HANDLE handle, MonoArray *src,
+ gint32 src_offset, gint32 count,
+ gint32 *error)
+{
+ guchar *buffer;
+ gboolean result;
+ guint32 n;
+
+ *error=ERROR_SUCCESS;
+
+ MONO_CHECK_ARG_NULL (src, 0);
+
+ if (src_offset > mono_array_length (src) - count) {
+ mono_set_pending_exception (mono_get_exception_argument ("array", "array too small. numBytes/offset wrong."));
+ return 0;
+ }
+
+ buffer = mono_array_addr (src, guchar, src_offset);
+ MONO_ENTER_GC_SAFE;
+ result = mono_w32file_write (handle, buffer, count, &n);
+ MONO_EXIT_GC_SAFE;
+
+ if (!result) {
+ *error=mono_w32error_get_last ();
+ return -1;
+ }
+
+ return (gint32)n;
+}
+
+gint64
+ves_icall_System_IO_MonoIO_Seek (HANDLE handle, gint64 offset, gint32 origin,
+ gint32 *error)
+{
+ gint32 offset_hi;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ offset_hi = offset >> 32;
+ offset = mono_w32file_seek (handle, (gint32) (offset & 0xFFFFFFFF), &offset_hi,
+ convert_seekorigin ((MonoSeekOrigin)origin));
+
+ if(offset==INVALID_SET_FILE_POINTER) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return offset | ((gint64)offset_hi << 32);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_Flush (HANDLE handle, gint32 *error)
+{
+ gboolean ret;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ ret=mono_w32file_flush (handle);
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+gint64
+ves_icall_System_IO_MonoIO_GetLength (HANDLE handle, gint32 *error)
+{
+ *error=ERROR_SUCCESS;
+ return mono_w32file_get_file_size (handle, error);
+}
+
+/* FIXME make gc suspendable */
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetLength (HANDLE handle, gint64 length,
+ gint32 *error)
+{
+ gint64 offset, offset_set;
+ gint32 offset_hi;
+ gint32 length_hi;
+ gboolean result;
+
+ *error=ERROR_SUCCESS;
+
+ /* save file pointer */
+
+ offset_hi = 0;
+ offset = mono_w32file_seek (handle, 0, &offset_hi, FILE_CURRENT);
+ if(offset==INVALID_SET_FILE_POINTER) {
+ *error=mono_w32error_get_last ();
+ return(FALSE);
+ }
+
+ /* extend or truncate */
+
+ length_hi = length >> 32;
+ offset_set=mono_w32file_seek (handle, length & 0xFFFFFFFF, &length_hi,
+ FILE_BEGIN);
+ if(offset_set==INVALID_SET_FILE_POINTER) {
+ *error=mono_w32error_get_last ();
+ return(FALSE);
+ }
+
+ result = mono_w32file_truncate (handle);
+ if(result==FALSE) {
+ *error=mono_w32error_get_last ();
+ return(FALSE);
+ }
+
+ /* restore file pointer */
+
+ offset_set=mono_w32file_seek (handle, offset & 0xFFFFFFFF, &offset_hi,
+ FILE_BEGIN);
+ if(offset_set==INVALID_SET_FILE_POINTER) {
+ *error=mono_w32error_get_last ();
+ return(FALSE);
+ }
+
+ return result;
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileTime (HANDLE handle, gint64 creation_time,
+ gint64 last_access_time,
+ gint64 last_write_time, gint32 *error)
+{
+ gboolean ret;
+ const FILETIME *creation_filetime;
+ const FILETIME *access_filetime;
+ const FILETIME *write_filetime;
+ MONO_ENTER_GC_SAFE;
+
+ *error=ERROR_SUCCESS;
+
+ if (creation_time < 0)
+ creation_filetime = NULL;
+ else
+ creation_filetime = (FILETIME *)&creation_time;
+
+ if (last_access_time < 0)
+ access_filetime = NULL;
+ else
+ access_filetime = (FILETIME *)&last_access_time;
+
+ if (last_write_time < 0)
+ write_filetime = NULL;
+ else
+ write_filetime = (FILETIME *)&last_write_time;
+
+ ret=mono_w32file_set_times (handle, creation_filetime, access_filetime, write_filetime);
+ if(ret==FALSE) {
+ *error=mono_w32error_get_last ();
+ }
+
+ MONO_EXIT_GC_SAFE;
+ return(ret);
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_get_ConsoleOutput ()
+{
+ return mono_w32file_get_console_output ();
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_get_ConsoleInput ()
+{
+ return mono_w32file_get_console_input ();
+}
+
+HANDLE
+ves_icall_System_IO_MonoIO_get_ConsoleError ()
+{
+ return mono_w32file_get_console_error ();
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_CreatePipe (HANDLE *read_handle, HANDLE *write_handle, gint32 *error)
+{
+ gboolean ret;
+
+ MONO_ENTER_GC_SAFE;
+ ret=mono_w32file_create_pipe (read_handle, write_handle, 0);
+ MONO_EXIT_GC_SAFE;
+
+ if(ret==FALSE) {
+ *error = mono_w32error_get_last ();
+ /* FIXME: throw an exception? */
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+MonoBoolean
+ves_icall_System_IO_MonoIO_DuplicateHandle (HANDLE source_process_handle, HANDLE source_handle,
+ HANDLE target_process_handle, HANDLE *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error)
+{
+ /* This is only used on Windows */
+ gboolean ret;
+
+ MONO_ENTER_GC_SAFE;
+#ifdef HOST_WIN32
+ ret=DuplicateHandle (source_process_handle, source_handle, target_process_handle, target_handle, access, inherit, options);
+#else
+ mono_w32handle_ref (source_handle);
+ *target_handle = source_handle;
+ ret = TRUE;
+#endif
+ MONO_EXIT_GC_SAFE;
+
+ if(ret==FALSE) {
+ *error = mono_w32error_get_last ();
+ /* FIXME: throw an exception? */
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+#ifndef HOST_WIN32
+gunichar2
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar ()
+{
+ return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar ()
+{
+ return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar ()
+{
+ if (IS_PORTABILITY_SET)
+ return (gunichar2) '\\'; /* backslash */
+ else
+ return (gunichar2) '/'; /* forward slash */
+}
+
+gunichar2
+ves_icall_System_IO_MonoIO_get_PathSeparator ()
+{
+ return (gunichar2) ':'; /* colon */
+}
+#endif /* !HOST_WIN32 */
+
+static const gunichar2
+invalid_path_chars [] = {
+#if defined (TARGET_WIN32)
+ 0x0022, /* double quote, which seems allowed in MS.NET but should be rejected */
+ 0x003c, /* less than */
+ 0x003e, /* greater than */
+ 0x007c, /* pipe */
+ 0x0008,
+ 0x0010,
+ 0x0011,
+ 0x0012,
+ 0x0014,
+ 0x0015,
+ 0x0016,
+ 0x0017,
+ 0x0018,
+ 0x0019,
+#endif
+ 0x0000 /* null */
+};
+
+MonoArray *
+ves_icall_System_IO_MonoIO_get_InvalidPathChars ()
+{
+ MonoError error;
+ MonoArray *chars;
+ MonoDomain *domain;
+ int i, n;
+
+ domain = mono_domain_get ();
+ n = sizeof (invalid_path_chars) / sizeof (gunichar2);
+ chars = mono_array_new_checked (domain, mono_defaults.char_class, n, &error);
+ if (mono_error_set_pending_exception (&error))
+ return NULL;
+
+ for (i = 0; i < n; ++ i)
+ mono_array_set (chars, gunichar2, i, invalid_path_chars [i]);
+
+ return chars;
+}
+
+void ves_icall_System_IO_MonoIO_Lock (HANDLE handle, gint64 position,
+ gint64 length, gint32 *error)
+{
+ *error=ERROR_SUCCESS;
+ mono_w32file_lock (handle, position, length, error);
+}
+
+void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position,
+ gint64 length, gint32 *error)
+{
+ *error=ERROR_SUCCESS;
+ mono_w32file_unlock (handle, position, length, error);
+}
+
+//Support for io-layer free mmap'd files.
+
+#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
+
+gint64
+mono_filesize_from_path (MonoString *string)
+{
+ MonoError error;
+ struct stat buf;
+ gint64 res;
+ char *path = mono_string_to_utf8_checked (string, &error);
+ mono_error_raise_exception (&error); /* OK to throw, external only without a good alternative */
+
+ MONO_ENTER_GC_SAFE;
+ if (stat (path, &buf) == -1)
+ res = -1;
+ else
+ res = (gint64)buf.st_size;
+
+ g_free (path);
+
+ MONO_EXIT_GC_SAFE;
+ return res;
+}
+
+gint64
+mono_filesize_from_fd (int fd)
+{
+ struct stat buf;
+ int res;
+
+ MONO_ENTER_GC_SAFE;
+ res = fstat (fd, &buf);
+ MONO_EXIT_GC_SAFE;
+
+ if (res == -1)
+ return (gint64)-1;
+
+ return (gint64)buf.st_size;
+}
+
+#endif
+
+#ifndef HOST_WIN32
+void mono_w32handle_dump (void);
+
+void ves_icall_System_IO_MonoIO_DumpHandles (void)
+{
+ mono_w32handle_dump ();
+}
+#endif /* !HOST_WIN32 */
--- /dev/null
+/*
+ * w32file.h: File IO internal calls
+ *
+ * Authors:
+ * Dick Porter (dick@ximian.com)
+ * Dan Lewis (dihlewis@yahoo.co.uk)
+ *
+ * (C) 2001 Ximian, Inc.
+ * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
+ */
+
+#ifndef _MONO_METADATA_W32FILE_H_
+#define _MONO_METADATA_W32FILE_H_
+
+#include <config.h>
+#include <glib.h>
+
+#include <mono/metadata/object-internals.h>
+#include <mono/utils/mono-compiler.h>
+
+G_BEGIN_DECLS
+
+/* This is a copy of System.IO.FileAccess */
+typedef enum {
+ FileAccess_Read=0x01,
+ FileAccess_Write=0x02,
+ FileAccess_ReadWrite=FileAccess_Read|FileAccess_Write
+} MonoFileAccess;
+
+/* This is a copy of System.IO.FileMode */
+typedef enum {
+ FileMode_CreateNew=1,
+ FileMode_Create=2,
+ FileMode_Open=3,
+ FileMode_OpenOrCreate=4,
+ FileMode_Truncate=5,
+ FileMode_Append=6
+} MonoFileMode;
+
+/* This is a copy of System.IO.FileShare */
+typedef enum {
+ FileShare_None=0x0,
+ FileShare_Read=0x01,
+ FileShare_Write=0x02,
+ FileShare_ReadWrite=FileShare_Read|FileShare_Write,
+ FileShare_Delete=0x04
+} MonoFileShare;
+
+/* This is a copy of System.IO.FileOptions */
+typedef enum {
+ FileOptions_None = 0,
+ FileOptions_Temporary = 1, // Internal. See note in System.IO.FileOptions
+ FileOptions_Encrypted = 0x4000,
+ FileOptions_DeleteOnClose = 0x4000000,
+ FileOptions_SequentialScan = 0x8000000,
+ FileOptions_RandomAccess = 0x10000000,
+ FileOptions_Asynchronous = 0x40000000,
+ FileOptions_WriteThrough = 0x80000000
+} MonoFileOptions;
+
+/* This is a copy of System.IO.SeekOrigin */
+typedef enum {
+ SeekOrigin_Begin=0,
+ SeekOrigin_Current=1,
+ SeekOrigin_End=2
+} MonoSeekOrigin;
+
+/* This is a copy of System.IO.MonoIOStat */
+typedef struct _MonoIOStat {
+ gint32 attributes;
+ gint64 length;
+ gint64 creation_time;
+ gint64 last_access_time;
+ gint64 last_write_time;
+} MonoIOStat;
+
+/* This is a copy of System.IO.FileAttributes */
+typedef enum {
+ FileAttributes_ReadOnly=0x00001,
+ FileAttributes_Hidden=0x00002,
+ FileAttributes_System=0x00004,
+ FileAttributes_Directory=0x00010,
+ FileAttributes_Archive=0x00020,
+ FileAttributes_Device=0x00040,
+ FileAttributes_Normal=0x00080,
+ FileAttributes_Temporary=0x00100,
+ FileAttributes_SparseFile=0x00200,
+ FileAttributes_ReparsePoint=0x00400,
+ FileAttributes_Compressed=0x00800,
+ FileAttributes_Offline=0x01000,
+ FileAttributes_NotContentIndexed=0x02000,
+ FileAttributes_Encrypted=0x04000,
+ FileAttributes_MonoExecutable= (int) 0x80000000
+} MonoFileAttributes;
+/* This is not used anymore
+typedef struct _MonoFSAsyncResult {
+ MonoObject obj;
+ MonoObject *state;
+ MonoBoolean completed;
+ MonoBoolean done;
+ MonoException *exc;
+ MonoWaitHandle *wait_handle;
+ MonoDelegate *async_callback;
+ MonoBoolean completed_synch;
+ MonoArray *buffer;
+ gint offset;
+ gint count;
+ gint original_count;
+ gint bytes_read;
+ MonoDelegate *real_cb;
+} MonoFSAsyncResult;
+*/
+/* System.IO.MonoIO */
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_CreateDirectory (MonoString *path, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_RemoveDirectory (MonoString *path, gint32 *error);
+
+MonoArray *
+ves_icall_System_IO_MonoIO_GetFileSystemEntries (MonoString *path,
+ MonoString *path_with_pattern,
+ gint mask, gint attrs,
+ gint32 *error);
+
+extern gpointer
+ves_icall_System_IO_MonoIO_FindFirstFile (MonoString *path_with_pattern,
+ MonoString **file_name,
+ gint32 *file_attr,
+ gint32 *ioerror);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_FindNextFile (gpointer hnd,
+ MonoString **file_name,
+ gint32 *file_attr,
+ gint32 *ioerror);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_FindCloseFile (gpointer hnd);
+
+extern MonoString *
+ves_icall_System_IO_MonoIO_FindFirst (MonoString *path,
+ MonoString *path_with_pattern,
+ gint32 *result_mask,
+ gint32 *error,
+ gpointer *handle);
+extern MonoString *
+ves_icall_System_IO_MonoIO_FindNext (gpointer handle, gint32 *result_mask, gint32 *error);
+
+extern int
+ves_icall_System_IO_MonoIO_FindClose (gpointer handle);
+
+extern MonoString *
+ves_icall_System_IO_MonoIO_GetCurrentDirectory (gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetCurrentDirectory (MonoString *path,
+ gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_MoveFile (MonoString *path, MonoString *dest,
+ gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest,
+ MonoBoolean overwrite, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_DeleteFile (MonoString *path, gint32 *error);
+
+extern gint32
+ves_icall_System_IO_MonoIO_GetFileAttributes (MonoString *path, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileAttributes (MonoString *path, gint32 attrs,
+ gint32 *error);
+
+extern gint32
+ves_icall_System_IO_MonoIO_GetFileType (gpointer handle, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_GetFileStat (MonoString *path, MonoIOStat *stat,
+ gint32 *error);
+
+extern gpointer
+ves_icall_System_IO_MonoIO_Open (MonoString *filename, gint32 mode,
+ gint32 access_mode, gint32 share, gint32 options,
+ gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_Close (gpointer handle, gint32 *error);
+
+extern gint32
+ves_icall_System_IO_MonoIO_Read (gpointer handle, MonoArray *dest,
+ gint32 dest_offset, gint32 count,
+ gint32 *error);
+
+extern gint32
+ves_icall_System_IO_MonoIO_Write (gpointer handle, MonoArray *src,
+ gint32 src_offset, gint32 count,
+ gint32 *error);
+
+extern gint64
+ves_icall_System_IO_MonoIO_Seek (gpointer handle, gint64 offset, gint32 origin,
+ gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_Flush (gpointer handle, gint32 *error);
+
+extern gint64
+ves_icall_System_IO_MonoIO_GetLength (gpointer handle, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetLength (gpointer handle, gint64 length,
+ gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_SetFileTime (gpointer handle, gint64 creation_time,
+ gint64 last_access_time,
+ gint64 last_write_time, gint32 *error);
+
+extern gpointer
+ves_icall_System_IO_MonoIO_get_ConsoleOutput (void);
+
+extern gpointer
+ves_icall_System_IO_MonoIO_get_ConsoleInput (void);
+
+extern gpointer
+ves_icall_System_IO_MonoIO_get_ConsoleError (void);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_CreatePipe (gpointer *read_handle, gpointer *write_handle, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_DuplicateHandle (gpointer source_process_handle, gpointer source_handle,
+ gpointer target_process_handle, gpointer *target_handle, gint32 access, gint32 inherit, gint32 options, gint32 *error);
+
+extern gunichar2
+ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar (void);
+
+extern gunichar2
+ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar (void);
+
+extern gunichar2
+ves_icall_System_IO_MonoIO_get_AltDirectorySeparatorChar (void);
+
+extern gunichar2
+ves_icall_System_IO_MonoIO_get_PathSeparator (void);
+
+extern MonoArray *
+ves_icall_System_IO_MonoIO_get_InvalidPathChars (void);
+
+extern void ves_icall_System_IO_MonoIO_Lock (gpointer handle, gint64 position,
+ gint64 length, gint32 *error);
+extern void ves_icall_System_IO_MonoIO_Unlock (gpointer handle, gint64 position,
+ gint64 length, gint32 *error);
+
+extern MonoBoolean
+ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName,
+ MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors,
+ gint32 *error);
+
+#if defined (TARGET_IOS) || defined (TARGET_ANDROID)
+
+MONO_RT_EXTERNAL_ONLY
+extern gint64
+mono_filesize_from_path (MonoString *path);
+
+extern gint64
+mono_filesize_from_fd (int fd);
+
+#endif
+
+void
+ves_icall_System_IO_MonoIO_DumpHandles (void);
+
+#if !defined(HOST_WIN32)
+
+#define GENERIC_READ 0x80000000
+#define GENERIC_WRITE 0x40000000
+#define GENERIC_EXECUTE 0x20000000
+#define GENERIC_ALL 0x10000000
+
+#define FILE_SHARE_READ 0x00000001
+#define FILE_SHARE_WRITE 0x00000002
+#define FILE_SHARE_DELETE 0x00000004
+
+#define CREATE_NEW 1
+#define CREATE_ALWAYS 2
+#define OPEN_EXISTING 3
+#define OPEN_ALWAYS 4
+#define TRUNCATE_EXISTING 5
+
+#define FILE_ATTRIBUTE_READONLY 0x00000001
+#define FILE_ATTRIBUTE_HIDDEN 0x00000002
+#define FILE_ATTRIBUTE_SYSTEM 0x00000004
+#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+#define FILE_ATTRIBUTE_ARCHIVE 0x00000020
+#define FILE_ATTRIBUTE_ENCRYPTED 0x00000040
+#define FILE_ATTRIBUTE_NORMAL 0x00000080
+#define FILE_ATTRIBUTE_TEMPORARY 0x00000100
+#define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+#define FILE_ATTRIBUTE_COMPRESSED 0x00000800
+#define FILE_ATTRIBUTE_OFFLINE 0x00001000
+#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+#define FILE_FLAG_OPEN_NO_RECALL 0x00100000
+#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
+#define FILE_FLAG_POSIX_SEMANTICS 0x01000000
+#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
+#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
+#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
+#define FILE_FLAG_RANDOM_ACCESS 0x10000000
+#define FILE_FLAG_NO_BUFFERING 0x20000000
+#define FILE_FLAG_OVERLAPPED 0x40000000
+#define FILE_FLAG_WRITE_THROUGH 0x80000000
+
+#define REPLACEFILE_WRITE_THROUGH 0x00000001
+#define REPLACEFILE_IGNORE_MERGE_ERRORS 0x00000002
+
+#define MAX_PATH 260
+
+#define INVALID_SET_FILE_POINTER ((guint32) 0xFFFFFFFF)
+#define INVALID_FILE_SIZE ((guint32) 0xFFFFFFFF)
+#define INVALID_FILE_ATTRIBUTES ((guint32) 0xFFFFFFFF)
+
+#define FILE_TYPE_UNKNOWN 0x0000
+#define FILE_TYPE_DISK 0x0001
+#define FILE_TYPE_CHAR 0x0002
+#define FILE_TYPE_PIPE 0x0003
+#define FILE_TYPE_REMOTE 0x8000
+
+#define FILE_BEGIN 0
+#define FILE_CURRENT 1
+#define FILE_END 2
+
+#define DRIVE_UNKNOWN 0
+#define DRIVE_NO_ROOT_DIR 1
+#define DRIVE_REMOVABLE 2
+#define DRIVE_FIXED 3
+#define DRIVE_REMOTE 4
+#define DRIVE_CDROM 5
+#define DRIVE_RAMDISK 6
+
+typedef struct {
+ guint16 wYear;
+ guint16 wMonth;
+ guint16 wDayOfWeek;
+ guint16 wDay;
+ guint16 wHour;
+ guint16 wMinute;
+ guint16 wSecond;
+ guint16 wMilliseconds;
+} SYSTEMTIME;
+
+typedef struct {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ guint32 dwHighDateTime;
+ guint32 dwLowDateTime;
+#else
+ guint32 dwLowDateTime;
+ guint32 dwHighDateTime;
+#endif
+} FILETIME;
+
+typedef struct {
+ guint32 dwFileAttributes;
+ FILETIME ftCreationTime;
+ FILETIME ftLastAccessTime;
+ FILETIME ftLastWriteTime;
+ guint32 nFileSizeHigh;
+ guint32 nFileSizeLow;
+ guint32 dwReserved0;
+ guint32 dwReserved1;
+ gunichar2 cFileName [MAX_PATH];
+ gunichar2 cAlternateFileName [14];
+} WIN32_FIND_DATA;
+
+#endif /* !defined(HOST_WIN32) */
+
+void
+mono_w32file_init (void);
+
+void
+mono_w32file_cleanup (void);
+
+gpointer
+mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs);
+
+gboolean
+mono_w32file_close (gpointer handle);
+
+gboolean
+mono_w32file_delete (const gunichar2 *name);
+
+gboolean
+mono_w32file_read (gpointer handle, gpointer buffer, guint32 numbytes, guint32 *bytesread);
+
+gboolean
+mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten);
+
+gboolean
+mono_w32file_flush (gpointer handle);
+
+gboolean
+mono_w32file_truncate (gpointer handle);
+
+guint32
+mono_w32file_seek (gpointer handle, gint32 movedistance, gint32 *highmovedistance, guint32 method);
+
+gboolean
+mono_w32file_move (gunichar2 *path, gunichar2 *dest, gint32 *error);
+
+gboolean
+mono_w32file_copy (gunichar2 *path, gunichar2 *dest, gboolean overwrite, gint32 *error);
+
+gboolean
+mono_w32file_lock (gpointer handle, gint64 position, gint64 length, gint32 *error);
+
+gboolean
+mono_w32file_replace (gunichar2 *destinationFileName, gunichar2 *sourceFileName, gunichar2 *destinationBackupFileName, guint32 flags, gint32 *error);
+
+gboolean
+mono_w32file_unlock (gpointer handle, gint64 position, gint64 length, gint32 *error);
+
+gpointer
+mono_w32file_get_console_output (void);
+
+gpointer
+mono_w32file_get_console_error (void);
+
+gpointer
+mono_w32file_get_console_input (void);
+
+gint64
+mono_w32file_get_file_size (gpointer handle, gint32 *error);
+
+gint
+mono_w32file_get_type (gpointer handle);
+
+gboolean
+mono_w32file_get_times (gpointer handle, FILETIME *create_time, FILETIME *access_time, FILETIME *write_time);
+
+gboolean
+mono_w32file_set_times (gpointer handle, const FILETIME *create_time, const FILETIME *access_time, const FILETIME *write_time);
+
+gboolean
+mono_w32file_filetime_to_systemtime (const FILETIME *file_time, SYSTEMTIME *system_time);
+
+gpointer
+mono_w32file_find_first (const gunichar2 *pattern, WIN32_FIND_DATA *find_data);
+
+gboolean
+mono_w32file_find_next (gpointer handle, WIN32_FIND_DATA *find_data);
+
+gboolean
+mono_w32file_find_close (gpointer handle);
+
+gboolean
+mono_w32file_create_directory (const gunichar2 *name);
+
+gboolean
+mono_w32file_remove_directory (const gunichar2 *name);
+
+guint32
+mono_w32file_get_attributes (const gunichar2 *name);
+
+gboolean
+mono_w32file_get_attributes_ex (const gunichar2 *name, MonoIOStat *stat);
+
+gboolean
+mono_w32file_set_attributes (const gunichar2 *name, guint32 attrs);
+
+guint32
+mono_w32file_get_cwd (guint32 length, gunichar2 *buffer);
+
+gboolean
+mono_w32file_set_cwd (const gunichar2 *path);
+
+gboolean
+mono_w32file_create_pipe (gpointer *readpipe, gpointer *writepipe, guint32 size);
+
+gint32
+mono_w32file_get_logical_drive (guint32 len, gunichar2 *buf);
+
+gboolean
+mono_w32file_get_disk_free_space (const gunichar2 *path_name, guint64 *free_bytes_avail, guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes);
+
+guint32
+mono_w32file_get_drive_type (const gunichar2 *root_path_name);
+
+gboolean
+mono_w32file_get_volume_information (const gunichar2 *path, gunichar2 *volumename, gint volumesize, gint *outserial, gint *maxcomp, gint *fsflags, gunichar2 *fsbuffer, gint fsbuffersize);
+
+G_END_DECLS
+
+#endif /* _MONO_METADATA_W32FILE_H_ */
#include "w32mutex.h"
#include "w32semaphore.h"
#include "w32event.h"
-#include "mono/io-layer/io-layer.h"
#include "mono/utils/mono-logger-internals.h"
#include "mono/utils/mono-coop-mutex.h"
mono_w32handle_unref (handle);
}
-/*
- * wapi_init:
- *
- * Initialize the io-layer.
- */
void
mono_w32handle_init (void)
{
return(GUINT_TO_POINTER(fd));
}
+gboolean
+mono_w32handle_close (gpointer handle)
+{
+ if (handle == INVALID_HANDLE_VALUE)
+ return FALSE;
+ if (handle == (gpointer) 0 && mono_w32handle_get_type (handle) != MONO_W32HANDLE_CONSOLE) {
+ /* Problem: because we map file descriptors to the
+ * same-numbered handle we can't tell the difference
+ * between a bogus handle and the handle to stdin.
+ * Assume that it's the console handle if that handle
+ * exists... */
+ return FALSE;
+ }
+
+ mono_w32handle_unref (handle);
+ return TRUE;
+}
+
gboolean
mono_w32handle_lookup (gpointer handle, MonoW32HandleType type,
gpointer *handle_specific)
gpointer
mono_w32handle_new_fd (MonoW32HandleType type, int fd, gpointer handle_specific);
+gboolean
+mono_w32handle_close (gpointer handle);
+
MonoW32HandleType
mono_w32handle_get_type (gpointer handle);
#include <pthread.h>
+#include "w32error.h"
#include "w32handle-namespace.h"
-#include "mono/io-layer/io-layer.h"
#include "mono/metadata/object-internals.h"
#include "mono/utils/mono-logger-internals.h"
#include "mono/utils/mono-threads.h"
#include "mono/metadata/w32handle.h"
+#define MAX_PATH 260
+
typedef struct {
MonoNativeThreadId tid;
guint32 recursion;
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating %s handle",
__func__, mono_w32handle_get_typename (type));
- SetLastError (ERROR_GEN_FAILURE);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
return NULL;
}
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different object. */
handle = NULL;
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
} else if (handle) {
/* Not an error, but this is how the caller is informed that the mutex wasn't freshly created */
- SetLastError (ERROR_ALREADY_EXISTS);
+ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
/* mono_w32handle_namespace_search_handle already adds a ref to the handle */
} else {
/* Need to blow away any old errors here, because code tests
* for ERROR_ALREADY_EXISTS on success (!) to see if a mutex
* was freshly created */
- SetLastError (ERROR_SUCCESS);
+ mono_w32error_set_last (ERROR_SUCCESS);
if (!name) {
mutex = mutex_create (owned);
} else {
mutex = namedmutex_create (owned, mono_string_chars (name));
- if (GetLastError () == ERROR_ALREADY_EXISTS)
+ if (mono_w32error_get_last () == ERROR_ALREADY_EXISTS)
*created = FALSE;
}
gboolean ret;
if (handle == NULL) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
case MONO_W32HANDLE_NAMEDMUTEX:
break;
default:
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
#include <mono/metadata/w32process.h>
#include <mono/metadata/w32process-internals.h>
#include <mono/metadata/w32process-unix-internals.h>
+#include <mono/metadata/w32error.h>
#include <mono/metadata/class.h>
#include <mono/metadata/class-internals.h>
#include <mono/metadata/object.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/exception.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/metadata/w32handle.h>
+#include <mono/metadata/w32file.h>
#include <mono/utils/mono-membar.h>
#include <mono/utils/mono-logger-internals.h>
#include <mono/utils/strenc.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/mono-mmap.h>
#include <mono/utils/strenc.h>
+#include <mono/utils/mono-io-portability.h>
+#include <mono/utils/w32api.h>
#ifndef MAXPATHLEN
#define MAXPATHLEN 242
static Process *processes;
static mono_mutex_t processes_mutex;
+static pid_t current_pid;
static gpointer current_process;
static const gunichar2 utf16_space_bytes [2] = { 0x20, 0 };
mono_w32handle_register_capabilities (MONO_W32HANDLE_PROCESS,
(MonoW32HandleCapability)(MONO_W32HANDLE_CAP_WAIT | MONO_W32HANDLE_CAP_SPECIAL_WAIT));
+ current_pid = getpid ();
+
memset (&process_handle, 0, sizeof (process_handle));
- process_handle.pid = wapi_getpid ();
+ process_handle.pid = current_pid;
process_set_defaults (&process_handle);
process_set_name (&process_handle);
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return 0;
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find pid %d", __func__, pid);
- SetLastError (ERROR_PROC_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PROC_NOT_FOUND);
return NULL;
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL",
__func__);
- SetLastError (ERROR_PATH_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PATH_NOT_FOUND);
goto free_strings;
}
if (args == NULL) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
- SetLastError (ERROR_PATH_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PATH_NOT_FOUND);
goto free_strings;
}
}
if (dir == NULL) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
- SetLastError (ERROR_PATH_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PATH_NOT_FOUND);
goto free_strings;
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
__func__, prog);
g_free (unquoted);
- SetLastError (ERROR_FILE_NOT_FOUND);
+ mono_w32error_set_last (ERROR_FILE_NOT_FOUND);
goto free_strings;
}
} else {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
__func__, prog);
g_free (unquoted);
- SetLastError (ERROR_FILE_NOT_FOUND);
+ mono_w32error_set_last (ERROR_FILE_NOT_FOUND);
goto free_strings;
}
}
/* Give up */
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find what to exec", __func__);
- SetLastError (ERROR_PATH_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PATH_NOT_FOUND);
goto free_strings;
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s",
__func__, token);
g_free (token);
- SetLastError (ERROR_FILE_NOT_FOUND);
+ mono_w32error_set_last (ERROR_FILE_NOT_FOUND);
goto free_strings;
}
} else {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Couldn't find executable %s", __func__, token);
g_free (token);
- SetLastError (ERROR_FILE_NOT_FOUND);
+ mono_w32error_set_last (ERROR_FILE_NOT_FOUND);
goto free_strings;
}
}
} else {
if (!is_executable (prog)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Executable permisson not set on %s", __func__, prog);
- SetLastError (ERROR_ACCESS_DENIED);
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
goto free_strings;
}
}
out_fd = GPOINTER_TO_UINT (startup_handles->output);
err_fd = GPOINTER_TO_UINT (startup_handles->error);
} else {
- in_fd = GPOINTER_TO_UINT (GetStdHandle (STD_INPUT_HANDLE));
- out_fd = GPOINTER_TO_UINT (GetStdHandle (STD_OUTPUT_HANDLE));
- err_fd = GPOINTER_TO_UINT (GetStdHandle (STD_ERROR_HANDLE));
+ in_fd = GPOINTER_TO_UINT (mono_w32file_get_console_input ());
+ out_fd = GPOINTER_TO_UINT (mono_w32file_get_console_output ());
+ err_fd = GPOINTER_TO_UINT (mono_w32file_get_console_error ());
}
/*
switch (pid = fork ()) {
case -1: /* Error */ {
- SetLastError (ERROR_OUTOFMEMORY);
+ mono_w32error_set_last (ERROR_OUTOFMEMORY);
ret = FALSE;
break;
}
mono_os_sem_destroy (&process->exit_sem);
g_free (process);
- SetLastError (ERROR_OUTOFMEMORY);
+ mono_w32error_set_last (ERROR_OUTOFMEMORY);
ret = FALSE;
break;
}
return ret;
#else
- SetLastError (ERROR_NOT_SUPPORTED);
+ mono_w32error_set_last (ERROR_NOT_SUPPORTED);
return FALSE;
#endif // defined (HAVE_FORK) && defined (HAVE_EXECVE)
}
*/
args = utf16_concat (utf16_quote, lpFile, utf16_quote, lpParameters == NULL ? NULL : utf16_space, lpParameters, NULL);
if (args == NULL) {
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
ret = FALSE;
goto done;
}
ret = process_create (NULL, args, lpDirectory, NULL, process_info);
g_free (args);
- if (!ret && GetLastError () == ERROR_OUTOFMEMORY)
+ if (!ret && mono_w32error_get_last () == ERROR_OUTOFMEMORY)
goto done;
if (!ret) {
args = utf16_concat (handler_utf16, utf16_space, utf16_quote, lpFile, utf16_quote,
lpParameters == NULL ? NULL : utf16_space, lpParameters, NULL);
if (args == NULL) {
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
ret = FALSE;
goto done;
}
ret = process_create (NULL, args, lpDirectory, NULL, process_info);
g_free (args);
if (!ret) {
- if (GetLastError () != ERROR_OUTOFMEMORY)
- SetLastError (ERROR_INVALID_DATA);
+ if (mono_w32error_get_last () != ERROR_OUTOFMEMORY)
+ mono_w32error_set_last (ERROR_INVALID_DATA);
ret = FALSE;
goto done;
}
/* Shell exec should not return a process handle when it spawned a GUI thing, like a browser. */
- CloseHandle (process_info->process_handle);
+ mono_w32handle_close (process_info->process_handle);
process_info->process_handle = NULL;
}
done:
if (ret == FALSE) {
- process_info->pid = -GetLastError ();
+ process_info->pid = -mono_w32error_get_last ();
} else {
process_info->thread_handle = NULL;
#if !defined(MONO_CROSS_COMPILE)
g_free (shell_path);
if (!ret)
- process_info->pid = -GetLastError ();
+ process_info->pid = -mono_w32error_get_last ();
return ret;
}
return FALSE;
}
- if (process_handle->pid == wapi_getpid ()) {
+ if (process_handle->pid == current_pid) {
*exitcode = STILL_ACTIVE;
return TRUE;
}
{
if (WAPI_IS_PSEUDO_PROCESS_HANDLE (handle))
return TRUE;
- return CloseHandle (handle);
+ return mono_w32handle_close (handle);
}
MonoBoolean
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find process %p", __func__, handle);
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
return TRUE;
switch (errno) {
- case EINVAL: SetLastError (ERROR_INVALID_PARAMETER); break;
- case EPERM: SetLastError (ERROR_ACCESS_DENIED); break;
- case ESRCH: SetLastError (ERROR_PROC_NOT_FOUND); break;
- default: SetLastError (ERROR_GEN_FAILURE); break;
+ case EINVAL: mono_w32error_set_last (ERROR_INVALID_PARAMETER); break;
+ case EPERM: mono_w32error_set_last (ERROR_ACCESS_DENIED); break;
+ case ESRCH: mono_w32error_set_last (ERROR_PROC_NOT_FOUND); break;
+ default: mono_w32error_set_last (ERROR_GEN_FAILURE); break;
}
return FALSE;
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return 0;
}
switch (errno) {
case EPERM:
case EACCES:
- SetLastError (ERROR_ACCESS_DENIED);
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
break;
case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PROC_NOT_FOUND);
break;
default:
- SetLastError (ERROR_GEN_FAILURE);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
}
return 0;
}
return MONO_W32PROCESS_PRIORITY_CLASS_NORMAL;
#else
- SetLastError (ERROR_NOT_SUPPORTED);
+ mono_w32error_set_last (ERROR_NOT_SUPPORTED);
return 0;
#endif
}
res = mono_w32handle_lookup (handle, MONO_W32HANDLE_PROCESS, (gpointer*) &process_handle);
if (!res) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
prio = -20;
break;
default:
- SetLastError (ERROR_INVALID_PARAMETER);
+ mono_w32error_set_last (ERROR_INVALID_PARAMETER);
return FALSE;
}
switch (errno) {
case EPERM:
case EACCES:
- SetLastError (ERROR_ACCESS_DENIED);
+ mono_w32error_set_last (ERROR_ACCESS_DENIED);
break;
case ESRCH:
- SetLastError (ERROR_PROC_NOT_FOUND);
+ mono_w32error_set_last (ERROR_PROC_NOT_FOUND);
break;
default:
- SetLastError (ERROR_GEN_FAILURE);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
}
}
return ret == 0;
#else
- SetLastError (ERROR_NOT_SUPPORTED);
+ mono_w32error_set_last (ERROR_NOT_SUPPORTED);
return FALSE;
#endif
}
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Bad dos signature 0x%x", __func__, dos_header->e_magic);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (map_size < sizeof(IMAGE_NT_HEADERS32) + GUINT32_FROM_LE (dos_header->e_lfanew)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File is too small: %d", __func__, map_size);
- SetLastError (ERROR_BAD_LENGTH);
+ mono_w32error_set_last (ERROR_BAD_LENGTH);
return(NULL);
}
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Bad NT signature 0x%x", __func__, nt_headers->Signature);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (resource_rva == 0) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No resources in file!", __func__);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (resource_dir == NULL) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find resource directory", __func__);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Bad dos signature 0x%x", __func__, dos_header->e_magic);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (map_size < sizeof(IMAGE_NT_HEADERS64) + GUINT32_FROM_LE (dos_header->e_lfanew)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File is too small: %d", __func__, map_size);
- SetLastError (ERROR_BAD_LENGTH);
+ mono_w32error_set_last (ERROR_BAD_LENGTH);
return(NULL);
}
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Bad NT signature 0x%x", __func__,
nt_headers->Signature);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (resource_rva == 0) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: No resources in file!", __func__);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (resource_dir == NULL) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Can't find resource directory", __func__);
- SetLastError (ERROR_INVALID_DATA);
+ mono_w32error_set_last (ERROR_INVALID_DATA);
return(NULL);
}
if (filename_ext == NULL) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unicode conversion returned NULL", __func__);
- SetLastError (ERROR_INVALID_NAME);
+ mono_w32error_set_last (ERROR_INVALID_NAME);
return(NULL);
}
- fd = _wapi_open (filename_ext, O_RDONLY, 0);
- if (fd == -1) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s: %s", __func__, filename_ext, strerror (errno));
+ fd = open (filename_ext, O_RDONLY, 0);
+ if (fd == -1 && (errno == ENOENT || errno == ENOTDIR) && IS_PORTABILITY_SET) {
+ gint saved_errno;
+ gchar *located_filename;
- SetLastError (_wapi_get_win32_file_error (errno));
- g_free (filename_ext);
+ saved_errno = errno;
- return(NULL);
+ located_filename = mono_portability_find_file (filename_ext, TRUE);
+ if (!located_filename) {
+ errno = saved_errno;
+
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s (1): %s", __func__, filename_ext, strerror (errno));
+
+ g_free (filename_ext);
+
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
+ return NULL;
+ }
+
+ fd = open (located_filename, O_RDONLY, 0);
+ if (fd == -1) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error opening file %s (2): %s", __func__, filename_ext, strerror (errno));
+
+ g_free (filename_ext);
+ g_free (located_filename);
+
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
+ return NULL;
+ }
+
+ g_free (located_filename);
}
if (fstat (fd, &statbuf) == -1) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error stat()ing file %s: %s", __func__, filename_ext, strerror (errno));
- SetLastError (_wapi_get_win32_file_error (errno));
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
g_free (filename_ext);
close (fd);
return(NULL);
if (statbuf.st_size < sizeof(IMAGE_DOS_HEADER)) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File %s is too small: %lld", __func__, filename_ext, statbuf.st_size);
- SetLastError (ERROR_BAD_LENGTH);
+ mono_w32error_set_last (ERROR_BAD_LENGTH);
g_free (filename_ext);
close (fd);
return(NULL);
if (file_map == NULL) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: Error mmap()int file %s: %s", __func__, filename_ext, strerror (errno));
- SetLastError (_wapi_get_win32_file_error (errno));
+ mono_w32error_set_last (mono_w32error_unix_to_win32 (errno));
g_free (filename_ext);
close (fd);
return(NULL);
#include <mono/metadata/threadpool-io.h>
#include <mono/utils/strenc.h>
#include <mono/utils/mono-proclib.h>
-#include <mono/io-layer/io-layer.h>
/* FIXME: fix this code to not depend so much on the internals */
#include <mono/metadata/class-internals.h>
#include <mono/metadata/w32handle.h>
+#include <mono/utils/w32api.h>
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
#include <shellapi.h>
#include "w32process.h"
#include "w32process-internals.h"
#include "w32process-win32-internals.h"
+#include "w32file.h"
#include "object.h"
#include "object-internals.h"
#include "class.h"
#include "class-internals.h"
#include "image.h"
#include "utils/mono-proclib.h"
-#include "io-layer/io-layer.h"
+#include "utils/w32api.h"
#define LOGDEBUG(...)
/* define LOGDEBUG(...) g_message(__VA_ARGS__) */
{
gpointer process_handle;
gpointer thread_handle;
- guint32 pid; /* Contains GetLastError () on failure */
+ guint32 pid; /* Contains mono_w32error_get_last () on failure */
guint32 tid;
MonoArray *env_variables;
MonoString *username;
#include "w32semaphore.h"
+#include "w32error.h"
#include "w32handle-namespace.h"
-#include "mono/io-layer/io-layer.h"
#include "mono/utils/mono-logger-internals.h"
#include "mono/metadata/w32handle.h"
+#define MAX_PATH 260
+
typedef struct {
guint32 val;
gint32 max;
if (handle == INVALID_HANDLE_VALUE) {
g_warning ("%s: error creating %s handle",
__func__, mono_w32handle_get_typename (type));
- SetLastError (ERROR_GEN_FAILURE);
+ mono_w32error_set_last (ERROR_GEN_FAILURE);
return NULL;
}
if (handle == INVALID_HANDLE_VALUE) {
/* The name has already been used for a different object. */
handle = NULL;
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
} else if (handle) {
/* Not an error, but this is how the caller is informed that the semaphore wasn't freshly created */
- SetLastError (ERROR_ALREADY_EXISTS);
+ mono_w32error_set_last (ERROR_ALREADY_EXISTS);
/* mono_w32handle_namespace_search_handle already adds a ref to the handle */
} else {
* for ERROR_ALREADY_EXISTS on success (!) to see if a
* semaphore was freshly created
*/
- SetLastError (ERROR_SUCCESS);
+ mono_w32error_set_last (ERROR_SUCCESS);
if (!name)
sem = sem_create (initialCount, maximumCount);
else
sem = namedsem_create (initialCount, maximumCount, mono_string_chars (name));
- *error = GetLastError ();
+ *error = mono_w32error_get_last ();
return sem;
}
MonoBoolean ret;
if (!handle) {
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
case MONO_W32HANDLE_NAMEDSEM:
break;
default:
- SetLastError (ERROR_INVALID_HANDLE);
+ mono_w32error_set_last (ERROR_INVALID_HANDLE);
return FALSE;
}
#include <sys/socket.h>
#endif
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
#ifndef HAVE_SOCKLEN_T
#define socklen_t int
typedef struct {
guint32 len;
gpointer buf;
-} WSABUF;
-
-typedef struct {
- guint32 Internal;
- guint32 InternalHigh;
- guint32 Offset;
- guint32 OffsetHigh;
- gpointer hEvent;
- gpointer handle1;
- gpointer handle2;
-} OVERLAPPED;
+} WSABUF, *LPWSABUF;
typedef struct {
gpointer Head;
guint32 HeadLength;
gpointer Tail;
guint32 TailLength;
-} TRANSMIT_FILE_BUFFERS;
+} TRANSMIT_FILE_BUFFERS, *LPTRANSMIT_FILE_BUFFERS;
typedef struct {
guint32 Data1;
guint8 Data4[8];
} GUID;
-typedef BOOL (WINAPI *LPFN_DISCONNECTEX)(SOCKET, OVERLAPPED*, guint32, guint32);
-typedef BOOL (WINAPI *LPFN_TRANSMITFILE)(SOCKET, HANDLE, guint32, guint32, OVERLAPPED*, TRANSMIT_FILE_BUFFERS*, guint32);
+typedef struct {
+ guint32 Internal;
+ guint32 InternalHigh;
+ guint32 Offset;
+ guint32 OffsetHigh;
+ gpointer hEvent;
+ gpointer handle1;
+ gpointer handle2;
+} OVERLAPPED;
#endif
mono_w32socket_recvfrom (SOCKET s, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking);
int
-mono_w32socket_recvbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking);
+mono_w32socket_recvbuffers (SOCKET s, LPWSABUF lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 *lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking);
int
mono_w32socket_send (SOCKET s, char *buf, int len, int flags, gboolean blocking);
mono_w32socket_sendto (SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking);
int
-mono_w32socket_sendbuffers (SOCKET s, WSABUF *lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking);
+mono_w32socket_sendbuffers (SOCKET s, LPWSABUF lpBuffers, guint32 dwBufferCount, guint32 *lpNumberOfBytesRecvd, guint32 lpFlags, gpointer lpOverlapped, gpointer lpCompletionRoutine, gboolean blocking);
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT | HAVE_UWP_WINAPI_SUPPORT)
BOOL
-mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, TRANSMIT_FILE_BUFFERS *lpTransmitBuffers, guint32 dwReserved, gboolean blocking);
+mono_w32socket_transmit_file (SOCKET hSocket, gpointer hFile, LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, guint32 dwReserved, gboolean blocking);
#endif
gint
mono_w32socket_ioctl (SOCKET sock, gint32 command, gchar *input, gint inputlen, gchar *output, gint outputlen, glong *written);
+gboolean
+mono_w32socket_close (SOCKET sock);
+
#endif /* HOST_WIN32 */
gint
#ifdef HAVE_SYS_SENDFILE_H
#include <sys/sendfile.h>
#endif
+#include <sys/stat.h>
#include "w32socket.h"
#include "w32socket-internals.h"
+#include "w32error.h"
#include "w32handle.h"
#include "utils/mono-logger-internals.h"
#include "utils/mono-poll.h"
}
if ((flags & TF_DISCONNECT) == TF_DISCONNECT)
- CloseHandle (handle);
+ mono_w32handle_close (handle);
return TRUE;
}
return 0;
}
+gboolean
+mono_w32socket_close (SOCKET sock)
+{
+ return mono_w32handle_close (GINT_TO_POINTER (sock));
+}
+
gint
mono_w32socket_set_blocking (SOCKET socket, gboolean blocking)
{
void
mono_w32socket_set_last_error (gint32 error)
{
- SetLastError (error);
+ mono_w32error_set_last (error);
}
gint32
mono_w32socket_get_last_error (void)
{
- return GetLastError ();
+ return mono_w32error_get_last ();
}
gint32
#include "w32socket.h"
#include "w32socket-internals.h"
+#include "utils/w32api.h"
+
#define LOGDEBUG(...)
void
#include <sys/types.h>
#include <mono/metadata/object.h>
-#include <mono/io-layer/io-layer.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/appdomain.h>
-#include <mono/metadata/file-io.h>
+#include <mono/metadata/w32file.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/threadpool-io.h>
#include <mono/metadata/w32handle.h>
#include <mono/metadata/w32socket.h>
#include <mono/metadata/w32socket-internals.h>
+#include <mono/metadata/w32error.h>
#include <time.h>
#ifdef HAVE_SYS_TIME_H
return WSAIoctl (sock, command, input, inputlen, output, outputlen, written, NULL, NULL);
}
+static gboolean
+mono_w32socket_close (SOCKET sock)
+{
+ return CloseHandle (sock);
+}
+
#endif /* HOST_WIN32 */
static void
mono_threadpool_io_remove_socket (GPOINTER_TO_INT (sock));
MONO_ENTER_GC_SAFE;
- CloseHandle (GINT_TO_POINTER (sock));
+ mono_w32socket_close ((SOCKET) sock);
MONO_EXIT_GC_SAFE;
}
/* FIXME: replace file by a proper fd that we can call open and close on, as they are interruptible */
- file = ves_icall_System_IO_MonoIO_Open (filename, FileMode_Open, FileAccess_Read, FileShare_Read, 0, werror);
-
+ file = mono_w32file_create (mono_string_chars (filename), OPEN_EXISTING, GENERIC_READ, FILE_SHARE_READ, 0);
if (file == INVALID_HANDLE_VALUE) {
- SetLastError (*werror);
+ *werror = mono_w32error_get_last ();
return FALSE;
}
mono_thread_info_install_interrupt (abort_syscall, (gpointer) (gsize) mono_native_thread_id_get (), &interrupted);
if (interrupted) {
- CloseHandle (file);
- SetLastError (WSAEINTR);
+ mono_w32file_close (file);
+ mono_w32error_set_last (WSAEINTR);
return FALSE;
}
mono_thread_info_uninstall_interrupt (&interrupted);
if (interrupted) {
- CloseHandle (file);
+ mono_w32file_close (file);
*werror = WSAEINTR;
return FALSE;
}
MONO_ENTER_GC_SAFE;
- CloseHandle (file);
+ mono_w32file_close (file);
MONO_EXIT_GC_SAFE;
boehm_libs= \
$(monodir)/mono/metadata/libmonoruntime.la \
- $(monodir)/mono/io-layer/libwapi.la \
$(monodir)/mono/utils/libmonoutils.la \
$(GLIB_LIBS) $(LIBICONV) \
$(libgc_libs)
sgen_libs = \
$(monodir)/mono/metadata/libmonoruntimesgen.la \
$(monodir)/mono/sgen/libmonosgen.la \
- $(monodir)/mono/io-layer/libwapi.la \
$(monodir)/mono/utils/libmonoutils.la \
$(GLIB_LIBS) $(LIBICONV)
boehm_static_libs= \
$(monodir)/mono/metadata/libmonoruntime-static.la \
- $(monodir)/mono/io-layer/libwapi.la \
$(monodir)/mono/utils/libmonoutils.la \
$(GLIB_LIBS) $(LIBICONV) \
$(libgc_static_libs)
sgen_static_libs = \
$(monodir)/mono/metadata/libmonoruntimesgen-static.la \
$(monodir)/mono/sgen/libmonosgen-static.la \
- $(monodir)/mono/io-layer/libwapi.la \
$(monodir)/mono/utils/libmonoutils.la \
$(GLIB_LIBS) $(LIBICONV)
if INSTALL_TESTING_AOT_FULL
FULLAOT_LIBS= \
- Mono.Dynamic.Interpreter.dll \
$(FULLAOT_LIBS_UNIVERSAL)
else
FULLAOT_LIBS= \
#include <mono/utils/json.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/profiler/mono-profiler-aot.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
#include "aot-compiler.h"
#include "seq-points.h"
gboolean mono_aot_is_direct_callable (MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
void mono_aot_mark_unused_llvm_plt_entry(MonoJumpInfo *patch_info) MONO_LLVM_INTERNAL;
char* mono_aot_get_plt_symbol (MonoJumpInfoType type, gconstpointer data) MONO_LLVM_INTERNAL;
-char* mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data);
+char* mono_aot_get_direct_call_symbol (MonoJumpInfoType type, gconstpointer data) MONO_LLVM_INTERNAL;
int mono_aot_get_method_index (MonoMethod *method) MONO_LLVM_INTERNAL;
MonoJumpInfo* mono_aot_patch_info_dup (MonoJumpInfo* ji) MONO_LLVM_INTERNAL;
amodule_lock (amodule);
- InterlockedIncrement (&mono_jit_stats.methods_aot);
-
- amodule->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
-
init_plt (amodule);
+ InterlockedIncrement (&mono_jit_stats.methods_aot);
+
if (method && method->wrapper_type)
g_hash_table_insert (amodule->method_to_code, method, code);
+ /* Commit changes since methods_loaded is accessed outside the lock */
+ mono_memory_barrier ();
+
+ amodule->methods_loaded [method_index / 32] |= 1 << (method_index % 32);
+
amodule_unlock (amodule);
if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION) {
#include "debugger-agent.h"
#include "mini.h"
#include "seq-points.h"
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
/*
* On iOS we can't use System.Environment.Exit () as it will do the wrong
#include <mono/metadata/marshal.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/io-layer/io-layer.h>
#include "mono/metadata/profiler.h"
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/io-layer/io-layer.h>
#include "mono/metadata/profiler.h"
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/threads.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/io-layer/io-layer.h>
#include "mono/metadata/profiler.h"
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/checked-build.h>
#include <mono/metadata/w32handle.h>
-#include <mono/io-layer/io-layer.h>
#include "mini.h"
#include "seq-points.h"
#include <mono/metadata/threads.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/debug-helpers.h>
-#include <mono/io-layer/io-layer.h>
#include "mono/metadata/profiler.h"
#include <mono/metadata/profiler-private.h>
#include <mono/metadata/mono-config.h>
#include <mono/utils/dtrace.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-threads-coop.h>
-#include <mono/io-layer/io-layer.h>
#include "mini.h"
#include "seq-points.h"
void mono_optimize_branches (MonoCompile *cfg);
void mono_blockset_print (MonoCompile *cfg, MonoBitSet *set, const char *name, guint idom);
-const char*mono_ji_type_to_string (MonoJumpInfoType type);
+const char*mono_ji_type_to_string (MonoJumpInfoType type) MONO_LLVM_INTERNAL;
void mono_print_ji (const MonoJumpInfo *ji);
void mono_print_ins_index (int i, MonoInst *ins);
GString *mono_print_ins_index_strbuf (int i, MonoInst *ins);
}
}
- g_free (predecessors);
+ g_array_free (predecessors, TRUE);
}
static void
check-local: $(check_targets)
EXTRA_DIST=mono-profiler-log.h \
+ mono-profiler-aot.h \
$(PLOG_TESTS_SRC) \
ptestrunner.pl \
$(suppression_DATA)
noinst_LTLIBRARIES = libtestlib.la
libtestlib_la_SOURCES =
-libtestlib_la_LIBADD = ../metadata/libmonoruntimesgen.la ../sgen/libmonosgen.la ../utils/libmonoutils.la ../io-layer/libwapi.la
+libtestlib_la_LIBADD = ../metadata/libmonoruntimesgen.la ../sgen/libmonosgen.la ../utils/libmonoutils.la
test_sgen_qsort_SOURCES = test-sgen-qsort.c
test_sgen_qsort_CFLAGS = $(test_cflags)
checked-build.c \
checked-build.h \
os-event.h \
- refcount.h
+ refcount.h \
+ w32api.h
arch_sources =
#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-counters.h>
-#include <mono/io-layer/io-layer.h>
#endif
typedef struct {
#include "mono-mmap.h"
#include "mono-counters.h"
#include "dlmalloc.h"
-#include <mono/io-layer/io-layer.h>
#include <mono/metadata/profiler-private.h>
#ifdef HAVE_VALGRIND_MEMCHECK_H
#include <valgrind/memcheck.h>
#include <mono/utils/mono-threads-coop.h>
#include <mono/utils/mono-threads-debug.h>
#include <mono/utils/os-event.h>
-
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/w32api.h>
#include <errno.h>
--- /dev/null
+
+#ifndef __MONO_UTILS_W32API_H__
+#define __MONO_UTILS_W32API_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#ifndef HOST_WIN32
+
+#define WAIT_FAILED ((gint) 0xFFFFFFFF)
+#define WAIT_OBJECT_0 ((gint) 0x00000000)
+#define WAIT_ABANDONED_0 ((gint) 0x00000080)
+#define WAIT_TIMEOUT ((gint) 0x00000102)
+#define WAIT_IO_COMPLETION ((gint) 0x000000C0)
+
+#define WINAPI
+
+typedef guint32 DWORD;
+typedef gboolean BOOL;
+typedef gint32 LONG;
+typedef guint32 ULONG;
+typedef guint UINT;
+
+typedef gpointer HANDLE;
+typedef gpointer HMODULE;
+
+#else
+
+#define __USE_W32_SOCKETS
+#include <winsock2.h>
+#include <windows.h>
+#include <winbase.h>
+/* The mingw version says: /usr/i686-pc-mingw32/sys-root/mingw/include/ws2tcpip.h:38:2: error: #error "ws2tcpip.h is not compatible with winsock.h. Include winsock2.h instead." */
+#ifdef _MSC_VER
+#include <ws2tcpip.h>
+#endif
+#include <psapi.h>
+
+/* Workaround for missing WSAPOLLFD typedef in mingw's winsock2.h
+ * that is required for mswsock.h below. Remove once
+ * http://sourceforge.net/p/mingw/bugs/1980/ is fixed. */
+#if defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION == 4
+typedef struct pollfd {
+ SOCKET fd;
+ short events;
+ short revents;
+} WSAPOLLFD, *PWSAPOLLFD, *LPWSAPOLLFD;
+#endif
+
+#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
+#include <mswsock.h>
+#endif
+
+#endif /* HOST_WIN32 */
+
+G_END_DECLS
+
+#endif /* __MONO_UTILS_W32API_H__ */
<ClCompile Include="..\mono\metadata\console-win32.c" />\r
<ClCompile Include="..\mono\metadata\property-bag.c" />\r
<ClCompile Include="..\mono\metadata\w32socket-win32.c" />\r
- <ClCompile Include="..\mono\metadata\file-io-windows.c" />\r
+ <ClCompile Include="..\mono\metadata\w32file-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32error-win32.c" />\r
<ClCompile Include="..\mono\metadata\icall-windows.c" />\r
<ClCompile Include="..\mono\metadata\marshal-windows.c" />\r
<ClCompile Include="..\mono\metadata\mono-security-windows.c" />\r
<ClCompile Include="..\mono\metadata\domain.c" />\r
<ClCompile Include="..\mono\metadata\environment.c" />\r
<ClCompile Include="..\mono\metadata\exception.c" />\r
- <ClCompile Include="..\mono\metadata\file-io.c" />\r
+ <ClCompile Include="..\mono\metadata\w32file.c" />\r
<ClCompile Include="..\mono\metadata\file-mmap-windows.c" />\r
<ClCompile Include="..\mono\metadata\filewatcher.c" />\r
<ClCompile Include="..\mono\metadata\gc-stats.c" />\r
<ClInclude Include="..\mono\metadata\dynamic-stream-internals.h" />\r
<ClInclude Include="..\mono\metadata\environment.h" />\r
<ClInclude Include="..\mono\metadata\exception.h" />\r
- <ClInclude Include="..\mono\metadata\file-io-internals.h" />\r
- <ClInclude Include="..\mono\metadata\file-io-windows-internals.h" />\r
- <ClInclude Include="..\mono\metadata\file-io.h" />\r
+ <ClInclude Include="..\mono\metadata\w32file-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\w32file-win32-internals.h" />\r
+ <ClInclude Include="..\mono\metadata\w32file.h" />\r
+ <ClInclude Include="..\mono\metadata\w32error.h" />\r
+ <ClInclude Include="..\mono\utils\w32api.h" />\r
<ClInclude Include="..\mono\metadata\filewatcher.h" />\r
<ClInclude Include="..\mono\metadata\gc-internals.h" />\r
<ClInclude Include="..\mono\metadata\handle.h" />\r
<ClCompile Include="..\mono\metadata\exception.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\file-io.c">\r
+ <ClCompile Include="..\mono\metadata\w32file.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\file-mmap-windows.c">\r
<ClCompile Include="..\mono\metadata\w32socket-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\file-io-windows.c">\r
+ <ClCompile Include="..\mono\metadata\w32file-win32.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32error-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\icall-windows.c">\r
<ClInclude Include="..\mono\metadata\exception.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\file-io.h">\r
+ <ClInclude Include="..\mono\metadata\w32file.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\metadata\w32error.h">\r
+ <Filter>Header Files</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="..\mono\utils\w32api.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
<ClInclude Include="..\mono\metadata\filewatcher.h">\r
<ClInclude Include="..\mono\metadata\console-win32-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\file-io-windows-internals.h">\r
+ <ClInclude Include="..\mono\metadata\w32file-win32-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="..\mono\metadata\file-io-internals.h">\r
+ <ClInclude Include="..\mono\metadata\w32file-internals.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
<ClInclude Include="..\mono\metadata\icall-internals.h">\r
<ClCompile Include="..\mono\metadata\console-win32.c" />\r
<ClCompile Include="..\mono\metadata\domain.c" />\r
<ClCompile Include="..\mono\metadata\environment.c" />\r
- <ClCompile Include="..\mono\metadata\file-io-windows.c" />\r
- <ClCompile Include="..\mono\metadata\file-io.c" />\r
+ <ClCompile Include="..\mono\metadata\w32file-win32.c" />\r
+ <ClCompile Include="..\mono\metadata\w32file.c" />\r
+ <ClCompile Include="..\mono\metadata\w32error-win32.c" />\r
<ClCompile Include="..\mono\metadata\filewatcher.c" />\r
<ClCompile Include="..\mono\metadata\gc.c" />\r
<ClCompile Include="..\mono\metadata\icall-windows.c" />\r
<ClCompile Include="..\mono\metadata\environment.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\file-io.c">\r
+ <ClCompile Include="..\mono\metadata\w32file.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="..\mono\metadata\filewatcher.c">\r
<ClCompile Include="..\mono\metadata\icall-windows.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="..\mono\metadata\file-io-windows.c">\r
+ <ClCompile Include="..\mono\metadata\w32file-win32.c">\r
+ <Filter>Source Files</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="..\mono\metadata\w32error-win32.c">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
</ItemGroup>\r
#include "mono/metadata/class.h"
#include "mono/metadata/object.h"
#include "mono/metadata/tabledefs.h"
-#include "mono/io-layer/wapi.h"
typedef struct {
const char *fname;
else
static_libs= \
$(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \
- $(top_builddir)/mono/io-layer/libwapi.la \
$(top_builddir)/mono/utils/libmonoutils.la \
$(GLIB_LIBS) $(LIBICONV) \
$(LIBGC_STATIC_LIBS)
pedump_LDADD = \
$(top_builddir)/mono/metadata/libmonoruntimesgen-static.la \
$(top_builddir)/mono/sgen/libmonosgen-static.la \
- $(top_builddir)/mono/io-layer/libwapi.la \
$(top_builddir)/mono/utils/libmonoutils.la \
$(LLVM_LIBS) \
$(LLVM_LDFLAGS) \