Git Product home page Git Product logo

longpath's Issues

Consider strong-naming with published SNK

To allow organizations which require strong-named assemblies so they can use code-signing for their internal projects to consume Pri.LongPath, consider strong-naming the package.

Different behaviour between Directory instance Exists property and Directory.Exists() static method

If I have an existing folder path that ends with a slash (e.g. "C:\test\folder") then the static method Directory.Exists(@"C:\test\folder") will find the folder and return true.

However, the instance property new Directory(@"C:\test\folder").Exists always seems to return false. If I remove the final slash from the end then it finds the folder and returns true.

This is easy to work around (always use the Static method), but I would have expected both the instance property and static method to behave the same (as they do in System.IO.Directory).

Directory.Exist return strange result

I'm trying your library.
The application is a bit special: it's a namespace extension.
At some place, I've this method:

public string CreateFolder(string mirror)
        {
            var local = Path.Combine(this._rootFolder, handleInvalidCharacters(mirror));
            if (!Directory.Exists(local))
                Directory.CreateDirectory(local);
            return local;
        }

This method is called maybe 10x in parallel by windows.
The Directory.Exists return true ... but the folder doesn't exists. It's never created.

In VS if I type these commands::

Pri.LongPath.Directory.Exists(local)
true
System.IO.Directory.Exists(local)
false

If I try in a "safe" environment with one simple execution, the method correctly return false

Any idea ?
Thank you

Wrong behavior of Directory.Delete for Reparse Points

Directory.Delete(string,bool) follows the reparse point, which is wrong.

System.IO.Directory.Delete:
"The behavior of this method differs slightly when deleting a directory that contains a reparse point, such as a symbolic link or a mount point. If the reparse point is a directory, such as a mount point, it is unmounted and the mount point is deleted. This method does not recurse through the reparse point. If the reparse point is a symbolic link to a file, the reparse point is deleted and not the target of the symbolic link. " https://msdn.microsoft.com/en-us/library/fxeahc5f%28v=vs.110%29.aspx

Fast fix would be:
public static void Delete(string path, bool recursive) {
var isReparsePoint=(new DirectoryInfo(path).Attributes & System.IO.FileAttributes.ReparsePoint) != 0;
if (isReparsePoint) { Delete(path); return;}
...
}

And by the way parameter "recursive" is never used!

CreateDirectory can fail due to race condition

You have the following in Directory.cs:

// To mimic Directory.CreateDirectory, we don't throw if the directory (not a file) already exists
...
// PR: Not sure this is even possible, we check for existance above.

You've obviously decided that it's not possible, and have commented out the code that deals with this (sorry I can't paste it here from work - my HTTP proxy blocks stuff that looks like code).

What happens if two people call this method at once from different threads?
This then throws, which it should not. :-(

DirectoryInfo.EnumerateFiles(); is missing

In v2.0.0-beta the DirectoryInfo.EnumerateFiles() method is no longer available from an instance of DirectoryInfo class for projects that are .Net 4.5+

This worked fine in v1.3.2 and emulated the behaviour of System.IO returning IEnumerable<FileInfo>

From my testing (using VS 2015 and the nuget prelease) it still works fine in .Net 4.0

Support UNC paths

Path.GetPathRoot(@"\\server\foo\bar\baz.txt") should return \\server\foo, but it returns \\ instead

DirectoryInfo.LastWriteTime throws FileNotFoundException on the root folder of a drive

System.IO.FileNotFoundException: File D:\ not found
File name: 'D:\'
   at Pri.LongPath.Common.ThrowIOError(Int32 errorCode, String maybeFullPath)
   at Pri.LongPath.FileSystemInfo.get_LastWriteTimeUtc()
   at Pri.LongPath.FileSystemInfo.get_LastWriteTime()
   at UserQuery.Main() in c:\Users\Tom\AppData\Local\Temp\LINQPad\_himmmwze\query_ijinft.cs:line 56

The same error occurs for all the creation/modification/las access properties.

In System.IO.DirectoryInfo, it works as expected.

Please make some INTERNAL methods PUBLIC in class 'File.cs'

class File has general purpose methods which are supposed to substitute some System.IO constructors.
Unfortunaltely they are INTERNAL and therefore not usable in the sence they are designed for.
Since File.cs ist static we even cant use inheritance to make them public.

Please help by making those methods in File.cs PUBLIC

public static class File
internal static StreamReader CreateStreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
internal static StreamWriter CreateStreamWriter(string path, bool append)
internal static StreamWriter CreateStreamWriter(string path, bool append, Encoding encoding)
internal static StreamWriter CreateText(string path, Encoding encoding)

Kind regards
efef77

Strong Name

Is it possible to put strong named assembly in the nuget package ?
Otherwise it's not possible to use the package is all situation (like mine)

File.GetLastWriteTimeUtc is inconsistent with Directory.GetLastWriteTimeUtc and other date methods

All these methods and properties throw an exception e.g. if the file is not found:

File.GetCreationTime[Utc]
File.GetLastAccessTime[Utc]
Directory.GetCreationTime[Utc]
Directory.GetLastAccessTime[Utc]
Directory.GetLastWriteTime[Utc]
FileSystemInfo.CreationTime[Utc]
FileSystemInfo.LastAccessTime[Utc]
FileSystemInfo.LastWriteTime[Utc]

But File.GetLastWriteTime[Utc] does not; it catches all exceptions and returns a default date (DateTime.FromFileTimeUtc(0L)). This is inconsistent.

System.UnauthorizedAccessException: Empty path

While investigating an issue I found this in my log file:

2016-10-26 09:36:41,141 - Scan - ERROR - MyApp.Business.SyncService - Error analyzing local changes
System.UnauthorizedAccessException: Empty path
   à Pri.LongPath.Common.ThrowIOError(Int32 errorCode, String maybeFullPath)
   à Pri.LongPath.FileSystemInfo.Refresh()
   à Pri.LongPath.DirectoryInfo.get_Exists()
   ...

I first tried to understand how I could possibly end-up with a DirectoryInfo with an empty path, since the path is validated at construction time, but looking at the code, I think the message is incorrect and misleading. The message "Empty path" comes from here:

            case NativeMethods.ERROR_ACCESS_DENIED:
                if (str.Length == 0)
                    throw new UnauthorizedAccessException("Empty path");
                else
                    throw new UnauthorizedAccessException(String.Format("Access denied accessing {0}", str));

because the maybeFullPath parameter is empty.

Common.ThrowIOError is called from here:

        catch (Exception)
        {
            if (state != State.Error)
                Common.ThrowIOError(Marshal.GetLastWin32Error(), string.Empty);
                    }

Is there any reason not to pass FullPath instead of string.Empty?

Problems with reserved DOS names

CON, AUX, LPT, etc. were reserved names in MsDos. For compatibility Windows Explorer still prevents you from creating files or directories with those names. But in fact Windows internally does support it (like it supports long filenames even tho the Explorer does not).

Would be great if those names would be handled correctly.
The following example demonstrates that. Pri.LongPath is not able to create a directory named "aux".

using System;
using System.Runtime.InteropServices;
using Pri.LongPath;

namespace MetaTree
{
    class Program
    {
        //Make sure temp already exists!
        private readonly static string temp = @"D:\Temp\";

        static void Main(string[] args)
        {
            //[System.ArgumentException]: The UNC path should be of the form \\server\share.
            Directory.CreateDirectory(temp + "aux");

            //With the WinAPI a prefix is needed, but it works
            CreateDirectory(@"\\?\" + temp + "aux", IntPtr.Zero);

            //Removes the aux Folder
            //WARNING: The "aux" folder can not be removed with the windows explorer
            RemoveDirectory(@"\\?\" + temp + "aux");
        }

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CreateDirectory(string lpPathName, IntPtr lpSecurityAttributes);

        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern bool RemoveDirectory(string lpPathName);
    }
}

Parameter is not correct - Pri.LongPath.Directory.BeginFind

I'm unfortunately using a version of Pri.LongPath that is a year or two old, so I'm not sure if this is still an issue. It is tough to reproduce though. I have a customer that hits this issue about once a week.

You can see below the stacktrace, and a mention of "System.IO.IOException - The parameter is incorrect" inside of Pri.LongPath.Directory.BeginFind().

At this point I do not have any additional information that could help in debugging this. Do you know where, within BeginFind(), I could maybe add some additional information to log files on this?

image

Path.GetUncRootLength does not support paths containing forward-slashes

In the Path class:

private static int GetUncRootLength(string path)
{
    var components = path.Split(new[] { DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
    var root = string.Format(@"\\{0}\{1}\", components[0], components[1]);
    return root.Length;
}

...throws an index out of bounds exception if you give it a path containing only forward-slashes (AltDirectorySeparatorChar). I think the Split should be for either. This occurs if you try to call Directory.Create() with a long path (i.e. > MAX_PATH chars) with forward-slashes, for example.

(Apologies - I'm behind an office firewall where I can't make a pull request / tests for this. :-( )

File Security not working

Im trying to set acl programatically, but "File.SetAccessControl(string path, FileSecurity FileSecurity)"didn't work, "File.GetAccessControl(string path)" worked fine!

;

Path.GetFileName throws if path is null

System.IO.Path.GetFileName returns null if the input is null. Pri.LongPath.Path.GetFileName used to do the same (since it simply delegated to System.IO.Path.GetFileName).

However it no longer does so, since it calls Path.NormalizeLongPath which throws if its input is null.

Some NUnit Tests failed due to current drive of installation - proposed solution enclosed

Regarding Pri.LongPath AssemblyVersion 2.0.1.0

Failed unit tests running the tests on D: drive instead of C: drive

  • UncDirectoryTests.TestGetDirectoryRoot()
  • UncDirectoryTests.TestGetPathRoot()
  • DirectoryInfoTests.TestMoveToDifferentRoot()
    These test where depending on a certain drive (C:)

I did some work on it:
So I recommend fixed test cases as follows.
They will run on any drive

-------------------------------
public class UncDirectoryTests
-------------------------------
[Test]
public void TestGetDirectoryRoot()
{   
    string plain = Directory.GetDirectoryRoot(directory);
    string unc = Directory.GetDirectoryRoot(uncDirectory);
    string must = @"\\localhost\X$\".Replace('X', plain[0]); // use current drive letter
    Assert.IsTrue(must.Equals(unc, StringComparison.InvariantCultureIgnoreCase));
}

[Test]
public void TestGetPathRoot()
{
    var root = Path.GetPathRoot(uncDirectory);
    Assert.IsNotNull(root);
    Assert.AreEqual(15, root.Length);
    var plain = Path.GetPathRoot(directory);
    string must = @"\\localhost\X$\".Replace('X', plain[0]); // use current drive letter
    Assert.IsTrue(must.Equals(root, StringComparison.InvariantCultureIgnoreCase));
}    
    
-------------------------------
public class DirectoryInfoTests
-------------------------------
[Test]
public void TestMoveToDifferentRoot()
{
    var randomFileName = Path.GetRandomFileName();
    var tempLongPathDirectory = Path.Combine(longPathDirectory, randomFileName);
    var di = new DirectoryInfo(tempLongPathDirectory);

    // get other drive letter
    char letter = longPathDirectory[0];
    if (letter < 'A' || letter >= 'Z') throw new Exception("invalid letter " + letter);
    letter = (char)(letter + 1); // next other drive
    string target = @"" + letter + @":\";
    Assert.Throws<IOException>(() => di.MoveTo(target)); // move to other drive
}

may some one update the test cases?
thx for great work on library

regards efef77

FileSystemWatcher is not implemented

Thanks for the nice package that solves 90% of my problems. The only thing left is that I am using a FileSystemWatcher. But that one is not implemented in LongPath. It fails with a pathtoolong exception. Are there any plans to include this?

AccessViolationException in Directory.cs

I wrote a simple program that reads folder permissions recursively for a large network share. Everything goes fine until it gets to a certain point then it throws an AccessViolationException pointing to this line:

var length = NativeMethods.GetSecurityDescriptorLength(byteArray);

Any Ideas?

IndexOutOfRangeException in Pri.LongPath.Path.NormalizeLongPath

I've just seen the following in some of our logs, with v2.0.24:

System.IndexOutOfRangeException: Index was outside the bounds of the array.
     at System.Text.StringBuilder.get_Chars(Int32 index)
     at Pri.LongPath.Path.NormalizeLongPath(String path, String parameterName)
     at Pri.LongPath.Path.TryNormalizeLongPath(String path, String& result)
     at Pri.LongPath.Common.Exists(String path, Boolean& isDirectory)
     at Pri.LongPath.File.Exists(String path)

Although sadly I'm not sure what path triggered this (although I think it was a relative path, if that helps). :-(

3 bugs - Directory.GetFiles - Directory.GetDirectories & Directory.Move

I tried your Pri.LongPath package yesterday & found the following issues:

  1. This fails to find matching files in sub-directories:
    Directory.GetFiles(FilePath,FileNamePattern,System.IO.SearchOption.AllDirectories)
  2. This fails to find matching directories in sub-directories:
    Directory.GetDirectories(FilePath,FolderNamePattern,System.IO.SearchOption.AllDirectories)
  3. This oftens throws a 'System.UnauthorizedAccessException: Access to the path denied' expection:
    Directory.Move(oldFolder, newFolder)

File.cs logs to Console while handling errors in opening

In GetFileHandle(...):

Console.WriteLine("error {0} with {1}\n{2}", ex.Message, normalizedPath, ex.StackTrace);
Console.WriteLine("{0} {1} {2} {3}", mode, access, share, options);

This should surely go into the exception object that is thrown, instead?

Directory.SetAccessControl does not set InheritanceFlags and PropagationFlags

Directory.SetAccessControl does not set InheritanceFlags and PropagationFlags
Directory.CreateDirectory(string path, DirectorySecurity directorySecurity) has the same problem

test to reproduce:

var localAdmins = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null);
security.AddAccessRule(new FileSystemAccessRule(localAdmins,
    FileSystemRights.FullControl,
    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
    PropagationFlags.NoPropagateInherit,
    AccessControlType.Allow));

Pri.LongPath.Directory.CreateDirectory(path);
Pri.LongPath.Directory.SetAccessControl(path, security);
ShowDirectorySecurity(path);
// FileSystemRights=FullControl, InheritanceFlags=[None], PropagationFlags=[None], AccessControlType=Allow

Directory.Delete(path);

System.IO.Directory.CreateDirectory(path);
System.IO.Directory.SetAccessControl(path, security);
ShowDirectorySecurity(path);
// FileSystemRights=FullControl, InheritanceFlags=[ContainerInherit, ObjectInherit], PropagationFlags=[NoPropagateInherit], AccessControlType=Allow

Directory.Delete(path);

Bug in Pri.LongPath.Path.GetDirectoryName when filename contains dot + whitespace

There is a bug in Pri.LongPath.Path.GetDirectoryName when the filename contains '. ' (dot and then whitespace).

System.IO.Path.GetDirectoryName("C:\\myfolder\\Con. approval.pdf")    // ==> C:\myfolder (correct)
Pri.LongPath.Path.GetDirectoryName("C:\\myfolder\\Con. approval.pdf") // ==> \\. (not correct)

Seems to be a win32 bug:

NativeMethods.GetFullPathName("C:\\myfolder\\Con. approval.pdf", (uint)buffer.Capacity, buffer, IntPtr.Zero) ==> buffer is set to \\.\Con - which is not correct

I have reported this here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx

Exception from fileInfo.Exists when file does not exist

I have the following exception sent in from a tester:

image

The filepath is ~160 characters and filename is another 60 characters, but the file does not exist. In fact, there's a good chance that the drive doesn't exist since this is my friend on a corporate computer with network drive.

Another thing I noticed is that fileInfo's createdTime and modifiedTime is much more sensitive (throws exceptions) when file does not exist verses the System.IO.FileInfo version. Not as important, I put a check first (if (fileInfo.Exists)), but now that throws exceptions too ;^)

Using .NET 4 Client Profile

The full .NET 4 is not needed to compile the library, so it'll be fine to use the .NET 4 Client Profile so that the DLL can be used even if the full .NET is not available.

remove acl

But now, i'm having some problems on

Directory.SetAccessControl(string Path, DirectorySecurity directorySecurity )
File.SetAccessControl(string Path, FileSecurity fileSecurity )

doesn't removes the rule on my folder or file, with System.IO works fine.

Here's how i'm using.
public void RemoveFileSecurity(FileSystemAccessRule rule)
{
FileSecurity fileSecurity = File.GetAccessControl(Path);
fileSecurity.RemoveAccessRule(rule);
System.IO.File.SetAccessControl(Path, fileSecurity);
}

thanks in advance!

Please consider dual-licensing under LGPL and MIT

Hi @peteraritchie, apologies that I need to bother you again with this.

Do you think it would be possible to dual license LongPath under MIT?

I think our usage in Paket would comply with LGPL, but realistically speaking, if the decision is between having to consult a lawyer, or just not implementing long-path support yet, option b) is more likely.

Thank you again!

(ref fsprojects/Paket#2584)

Difference from File.Exists when space is present in directory

I admit that this is a really strange one, but here is the situation

Create a c:\temp\test.txt in your disk

Run this piece of code

string file = @"c:\temp \test.txt";
Console.WriteLine("System.IO.File.Exists(file) = {0}", System.IO.File.Exists(file));
Console.WriteLine("Pri.LongPath.File.Exists(file) = {0}", Pri.LongPath.File.Exists(file));
Console.ReadKey();

If you look at the code I've inserted a space between temp and directory separator. Actually the standard File.IO.File.exists returns true, while Pri.LongPath.File returns false.

Gian Maria.

File.Copy throws an IOException that does not contain the filename if the file exists

System.IO.File.Copy(@"e:\foo", @"e:\bar", false);

...gives "The file 'e:\bar' already exists." in the thrown IOException's Message, whereas:

Pri.LongPath.File.Copy(@"e:\foo", @"e:\bar", false);

...gives only "The file exists."
I think this is because File.cs:135 is using throw Common.GetExceptionFromLastWin32Error() instead of Common.ThrowIOError(errorCode, fullPath).

Maybe GetExceptionFromLastWin32Error() could do with taking an optional fullPath argument? It looks like perhaps ThrowIOError and GetExceptionFromLastWin32Error ought to be unified, given what they do - not sure on your thoughts on that.

Thanks for the brilliantly useful library, by the way! :-)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.