Factory functions for PurePaths
Beispiel #1
0
        /// <inheritdoc/>
        public override WindowsPath Resolve()
        {
            if (_cachedResolve != null)
            {
                return(_cachedResolve);
            }

            using (var fs = File.OpenRead(PurePath.ToString()))
            {
                if (fs.SafeFileHandle == null)
                {
                    return(this);
                }
                var builder = new StringBuilder(512);
                GetFinalPathNameByHandle(fs.SafeFileHandle.DangerousGetHandle(),
                                         builder, builder.Capacity, 0);
                var newPath = builder.ToString();

                if (newPath.StartsWith(ExtendedLengthPrefix) &&
                    !PurePath.ToString().StartsWith(ExtendedLengthPrefix))
                {
                    newPath = newPath.Substring(ExtendedLengthPrefix.Length);
                }
                return(_cachedResolve = new WindowsPath(newPath));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Return true if the path points to a junction. These are distinct
        /// from symlinks.
        /// </summary>
        /// <returns></returns>
        public bool IsJunction()
        {
            ReparsePoint rep;

            return(ReparsePoint.TryCreate(PurePath.ToString(), out rep) &&
                   rep.Tag == ReparsePoint.TagType.JunctionPoint);
        }
Beispiel #3
0
        /// <inheritdoc/>
        public override bool IsSymlink()
        {
            ReparsePoint rep;

            return(ReparsePoint.TryCreate(PurePath.ToString(), out rep) &&
                   rep.Tag == ReparsePoint.TagType.SymbolicLink);
        }
Beispiel #4
0
        /// <inheritdoc/>
        protected override StatInfo Stat(bool flushCache)
        {
            if (_cachedStat != null && !flushCache)
            {
                return(_cachedStat);
            }

            // http://www.delorie.com/gnu/docs/glibc/libc_284.html
            var info = new FileInfo(PurePath.ToString());
            var stat = new StatInfo
            {
                Size   = info.Length,
                ATime  = info.LastAccessTimeUtc,
                MTime  = info.LastWriteTimeUtc,
                CTime  = info.CreationTimeUtc,
                Device = 0,
                Inode  = 0,
                Gid    = 0,
                Uid    = 0,
                Mode   = 0 // TODO not implemented
            };

            _cachedStat = stat;
            return(stat);
        }
Beispiel #5
0
        /// <summary>
        /// Gets the type of the file in the filesystem. This is
        /// unrelated to the extension/contents, rather it is an
        /// enumeration between whether the path points to a directory,
        /// file, symlink, socket, block device, etc.
        /// This is currently only relevant to Posix/Linux systems.
        /// </summary>
        /// <returns></returns>
        public FileType GetFileType()
        {
            var path = PurePath.ToString();
            var err  = Native.lstat(path, out var info);

            if (err != 0)
            {
                var actualError = Marshal.GetLastWin32Error();
                if (actualError == 2)
                {
                    return(FileType.DoesNotExist);
                }
                throw new ApplicationException("Error: " + actualError);
            }

            var fmt = info.st_mode & Native.FileTypeFormat;

            return(fmt switch
            {
                Native.FileTypeSymlink => FileType.SymbolicLink,
                Native.FileTypeDirectory => FileType.Directory,
                Native.FileTypeCharacterDevice => FileType.CharacterDevice,
                Native.FileTypeBlockDevice => FileType.BlockDevice,
                Native.FileTypeFifo => FileType.Fifo,
                Native.FileTypeSocket => FileType.Socket,
                Native.FileTypeRegularFile => FileType.RegularFile,
                _ => throw new ApplicationException($"Unknown file type {fmt}")
            });
Beispiel #6
0
 /// <summary>
 /// Compare two <see cref="PureWindowsPath"/> for equality.
 /// Case insensitive.
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public bool Equals(WindowsPath other)
 {
     if (other is null)
     {
         return(false);
     }
     return(PurePath.Equals(other.PurePath));
 }
Beispiel #7
0
        /// <summary>
        /// Convert a path that uses the short 8.3 name (e.g. DOCUME~2.docx)
        /// into its long path.
        /// </summary>
        /// <returns></returns>
        public WindowsPath ToLongPath()
        {
            var oldPath = PurePath.ToString();
            var newPath = new StringBuilder(255);

            if (GetLongPathName(oldPath, newPath, newPath.Capacity) == 0)
            {
                return(this);
            }
            return(new WindowsPath(PurePath.WithFilename(newPath.ToString()).ToString()));
        }
Beispiel #8
0
        /// <inheritdoc/>
        public override WindowsPath ExpandUser()
        {
            var homeDir = new PureWindowsPath("~");

            if (homeDir < PurePath)
            {
                var newDir = new PureWindowsPath(Environment.GetEnvironmentVariable("USERPROFILE"));
                return(new WindowsPath(newDir.Join(PurePath.RelativeTo(homeDir))));
            }
            return(this);
        }
Beispiel #9
0
 /// <inheritdoc/>
 public override string ToString()
 {
     return(PurePath.ToString());
 }
Beispiel #10
0
 /// <inheritdoc/>
 public override int GetHashCode()
 {
     return(PurePath.GetHashCode());
 }
Beispiel #11
0
 /// <summary>
 /// Compare two <see cref="PureWindowsPath"/> for equality.
 /// Case insensitive.
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public bool Equals(WindowsPath other)
 {
     return(PurePath.Equals(other.PurePath));
 }
Beispiel #12
0
        /// <inheritdoc/>
        protected override StatInfo Stat(bool flushCache)
        {
            if (_cachedStat != null && !flushCache)
            {
                return(_cachedStat);
            }

            var path = PurePath.ToString();
            var err  = Posix.Native.stat64(path, out var info);

            if (err != 0)
            {
                var actualError = Marshal.GetLastWin32Error();
                if (actualError == 2)
                {
                    throw new FileNotFoundException("Cannot stat file that does not exist.", path);
                }
                throw new ApplicationException("Error: " + actualError);
            }

            var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var atim  = epoch.AddSeconds(info.st_atim.tv_sec);

            if (info.st_atim.tv_nsec != 0)
            {
                atim = atim.AddTicks((long)(info.st_atim.tv_nsec / 100));
            }
            var mtim = epoch.AddSeconds(info.st_mtim.tv_sec);

            if (info.st_mtim.tv_nsec != 0)
            {
                mtim = mtim.AddTicks((long)(info.st_mtim.tv_nsec / 100));
            }
            var ctim = epoch.AddSeconds(info.st_ctim.tv_sec);

            if (info.st_ctim.tv_nsec != 0)
            {
                ctim = ctim.AddTicks((long)(info.st_ctim.tv_nsec / 100));
            }
            var stat = new StatInfo
            {
                Size        = info.st_size,
                ATime       = atim,
                MTime       = mtim,
                CTime       = ctim,
                Device      = (long)info.st_dev,
                Inode       = (long)info.st_ino,
                Gid         = info.st_uid,
                Uid         = info.st_gid,
                ModeDecimal = info.st_mode,
                Mode        = Convert.ToString(info.st_mode & (Native.SetBits | Native.UserBits | Native.GroupBits | Native.OtherBits), 8).PadLeft(4, '0'),
                NumLinks    = (long)info.st_nlink
            };

            try
            {
                _cachedStat = stat;
            }
            // Yes, this assignment throws a NRE if the struct alignment for pinvoke is wrong.
            // It overwrites 'this' in the stack with null.
            catch (NullReferenceException e)
            {
                throw new NotImplementedException("Layout of stat call not supported on this platform (Only supports Ubuntu x86_64 and anything compatible).", e);
            }
            return(stat);
        }