コード例 #1
0
        public override IUnsafeMemoryMap MemoryMapFile(string fileName)
        {
            int file = Syscall.open(fileName, OpenFlags.O_RDONLY);

            Stat  fileStat = new Stat();
            void *pMem     = null;

            try{
                if (file == -1)
                {
                    throw new FileLoadException("Unable to load file", fileName, new PosixException(Stdlib.GetLastError()));
                }

                int res = Syscall.fstat(file, out fileStat);

                if (res == -1)
                {
                    Syscall.close(file);
                    throw new FileLoadException("Unable to load file", fileName, new PosixException(Stdlib.GetLastError()));
                }

                pMem = (void *)Syscall.mmap(
                    IntPtr.Zero,
                    (ulong)fileStat.st_size,
                    MmapProts.PROT_READ,
                    MmapFlags.MAP_PRIVATE,
                    file,
                    0
                    );

                if (pMem == null)
                {
                    throw new FileLoadException(
                              "Unable to load file",
                              fileName,
                              new PosixException(Stdlib.GetLastError())
                              );
                }

                return(new PosixMemoryMap(pMem, checked ((uint)fileStat.st_size)));
            }
            catch {
                if (file != -1)
                {
                    Syscall.close(file);
                }
                if (pMem != null)
                {
                    Syscall.munmap((IntPtr)pMem, checked ((ulong)fileStat.st_size));
                }
                throw;
            }
        }
コード例 #2
0
        public override void SetPermissions(string path, string mask, string user, string group)
        {
            Logger.Debug("Setting permissions: {0} on {1}", mask, path);

            var filePermissions = NativeConvert.FromOctalPermissionString(mask);

            if (Syscall.chmod(path, filePermissions) < 0)
            {
                var error = Stdlib.GetLastError();

                throw new LinuxPermissionsException("Error setting file permissions: " + error);
            }

            if (String.IsNullOrWhiteSpace(user) || String.IsNullOrWhiteSpace(group))
            {
                Logger.Debug("User or Group for chown not configured, skipping chown.");
                return;
            }

            uint userId;
            uint groupId;

            if (!uint.TryParse(user, out userId))
            {
                var u = Syscall.getpwnam(user);

                if (u == null)
                {
                    throw new LinuxPermissionsException("Unknown user: {0}", user);
                }

                userId = u.pw_uid;
            }

            if (!uint.TryParse(group, out groupId))
            {
                var g = Syscall.getgrnam(group);

                if (g == null)
                {
                    throw new LinuxPermissionsException("Unknown group: {0}", group);
                }

                groupId = g.gr_gid;
            }

            if (Syscall.chown(path, userId, groupId) < 0)
            {
                var error = Stdlib.GetLastError();

                throw new LinuxPermissionsException("Error setting file owner and/or group: " + error);
            }
        }
コード例 #3
0
        protected override Errno OnOpenDirectory(string path, OpenedPathInfo info)
        {
            IntPtr dp = Syscall.opendir(basedir + path);

            if (dp == IntPtr.Zero)
            {
                return(Stdlib.GetLastError());
            }

            info.Handle = dp;
            return(0);
        }
コード例 #4
0
        /// <summary>
        ///   Moves file from <paramref name="sourcePath"/> to <paramref name="destinationPath"/> the same way <see
        ///   cref="System.IO.File.Move"/> does but it checks whether the file pointed to by <paramref
        ///   name="sourcePath"/> is a dangling symlink and, if yes, it does not call <see cref="System.IO.File.Move"/>
        ///   but instead uses <c>readlink(2)</c> and <c>symlink(2)</c> to recreate the symlink at the destination. This
        ///   is to work around a bug in Mono 6 series which will throw an exception when trying to move a dangling
        ///   symlink.
        /// </summary>
        public static void FileMove(string sourcePath, string destinationPath)
        {
            if (String.IsNullOrEmpty(sourcePath))
            {
                throw new ArgumentException("must not be null or empty", nameof(sourcePath));
            }
            if (String.IsNullOrEmpty(destinationPath))
            {
                throw new ArgumentException("must not be null or empty", nameof(destinationPath));
            }

            int ret = Syscall.lstat(sourcePath, out Stat sbuf);

            if (ret != 0 || (ret == 0 && (sbuf.st_mode & FilePermissions.S_IFLNK) != FilePermissions.S_IFLNK))
            {
                // Not a symlink or an error, just call to the BCL and let it handle both situations
                File.Move(sourcePath, destinationPath);
                return;
            }

            // Source is a symlink
            ret = Syscall.stat(sourcePath, out sbuf);
            if (ret < 0)
            {
                Log.DebugLine($"stat on {sourcePath} returned {ret}. Errno: {Stdlib.GetLastError ()}");
            }
            if (!FileIsDanglingSymlink(sourcePath))
            {
                // let BCL handle it
                File.Move(sourcePath, destinationPath);
                return;
            }

            Log.DebugLine($"Moving a dangling symlink from {sourcePath} to {destinationPath}");
            // We have a dangling symlink, we'll just recreate it at the destination and remove the source
            var sb = new StringBuilder(checked ((int)sbuf.st_size));

            ret = Syscall.readlink(sourcePath, sb);
            if (ret < 0)
            {
                throw new IOException($"Failed to read a symbolic link '{sourcePath}'. {Stdlib.strerror (Stdlib.GetLastError ())}");
            }

            string sourceLinkContents = sb.ToString();

            Log.DebugLine($"Source symlink {sourcePath} points to: {sourceLinkContents}");
            ret = Syscall.symlink(sourceLinkContents, destinationPath);
            if (ret < 0)
            {
                throw new IOException($"Failed to create a symbolic link '{destinationPath}' -> '{sourceLinkContents}'. {Stdlib.strerror (Stdlib.GetLastError ())}");
            }
        }
コード例 #5
0
ファイル: DiskProvider.cs プロジェクト: nimeshjm/Sonarr
        private void SetPermissions(string path, string mask)
        {
            Logger.Debug("Setting permissions: {0} on {1}", mask, path);

            var filePermissions = NativeConvert.FromOctalPermissionString(mask);

            if (Syscall.chmod(path, filePermissions) < 0)
            {
                var error = Stdlib.GetLastError();

                throw new LinuxPermissionsException("Error setting file permissions: " + error);
            }
        }
コード例 #6
0
        static bool FileIsDanglingSymlink(string path)
        {
            int ret = Syscall.stat(path, out Stat sbuf);

            Log.DebugLine($"stat on {path} returned {ret}. Errno: {Stdlib.GetLastError ()}");
            if (ret == 0 || (ret < 0 && Stdlib.GetLastError() != Errno.ENOENT))
            {
                // Either a valid symlink or an error other than ENOENT
                return(false);
            }

            return(true);
        }
コード例 #7
0
        public override Errno OnRenamePath(string oldpath, string newpath)
        {
            Trace.WriteLine($"OnRenamePath {oldpath} to {newpath}");

            int r = Stdlib.rename(oldpath, newpath);

            if (r < 0)
            {
                return(Stdlib.GetLastError());
            }

            return(0);
        }
コード例 #8
0
ファイル: LinuxDisk.cs プロジェクト: GMMan/samsung-card-auth
 /// <summary>
 /// Instantiates a new instance of <see cref="LinuxDisk"/>.
 /// </summary>
 /// <param name="path">The path to the disk device node.</param>
 public LinuxDisk(string path)
 {
     if (string.IsNullOrEmpty(path))
     {
         throw new ArgumentNullException(nameof(path));
     }
     fd = Syscall.open(path, OpenFlags.O_RDONLY);
     if (fd == -1)
     {
         var errno = Stdlib.GetLastError();
         throw new IOException(UnixMarshal.GetErrorDescription(errno));
     }
     DisplayName = path;
 }
コード例 #9
0
        public static string GetLoginName()
        {
            int           num;
            StringBuilder stringBuilder = new StringBuilder(4);

            do
            {
                StringBuilder capacity = stringBuilder;
                capacity.Capacity = capacity.Capacity * 2;
                num = Syscall.getlogin_r(stringBuilder, (ulong)stringBuilder.Capacity);
            }while (num == -1 && Stdlib.GetLastError() == Errno.ERANGE);
            UnixMarshal.ThrowExceptionForLastErrorIf(num);
            return(stringBuilder.ToString());
        }
コード例 #10
0
        public virtual Errno FlushHandle(string path, OpenedPathInfo info)
        {
            /* This is called from every close on an open file, so call the
            *  close on the underlying filesystem.  But since flush may be
            *  called multiple times for an open file, this must not really
            *  close the file.  This is important if used on a network
            *  filesystem like NFS which flush the data/metadata on close() */
            int r = Syscall.close(Syscall.dup((int)info.Handle));

            if (r == -1)
            {
                return(Stdlib.GetLastError());
            }
            return(0);
        }
コード例 #11
0
ファイル: ReadlinkTest.cs プロジェクト: zcz527/mono
        void CreateLink(string s)
        {
            string link = UnixPath.Combine(TempFolder, "link");

            //File.Delete (link); // Fails for long link target paths
            if (Syscall.unlink(link) < 0 && Stdlib.GetLastError() != Errno.ENOENT)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }

            if (Syscall.symlink(s, link) < 0)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
        }
コード例 #12
0
        public UnixSignal(Mono.Unix.Native.RealTimeSignum rtsig)
        {
            this.signum      = NativeConvert.FromRealTimeSignum(rtsig);
            this.signal_info = UnixSignal.install(this.signum);
            Errno lastError = Stdlib.GetLastError();

            if (this.signal_info == IntPtr.Zero)
            {
                if (lastError != Errno.EADDRINUSE)
                {
                    throw new ArgumentException("Unable to handle signal", "signum");
                }
                throw new ArgumentException("Signal registered outside of Mono.Posix", "signum");
            }
        }
コード例 #13
0
        private bool Refresh(bool throwException)
        {
            int num = Syscall.statvfs(this.mount_point, out this.stat);

            if (num == -1 && throwException)
            {
                Errno lastError = Stdlib.GetLastError();
                throw new InvalidOperationException(UnixMarshal.GetErrorDescription(lastError), new UnixIOException(lastError));
            }
            if (num == -1)
            {
                return(false);
            }
            return(true);
        }
コード例 #14
0
        public virtual void GetExtendedAttribute(string path, string name, byte[] value, out int bytesWritten)
        {
            bytesWritten = (int)Syscall.lgetxattr(path.GetPath(_source), name, value, (ulong)(value?.Length ?? 0));
            if (bytesWritten != -1)
            {
                return;
            }

            var err = Stdlib.GetLastError();

            if (err != Errno.ENODATA)
            {
                throw new NativeException((int)err);
            }
        }
コード例 #15
0
 public static bool ShouldRetrySyscall(int r, out Errno errno)
 {
     errno = (Errno)0;
     if (r == -1)
     {
         Errno lastError = Stdlib.GetLastError();
         Errno errno1    = lastError;
         errno = lastError;
         if (errno1 == Errno.EINTR)
         {
             return(true);
         }
     }
     return(false);
 }
コード例 #16
0
 private static bool TryDoFileLocking(int fd, bool lockFile, FlockOperation?specificFlag = null)
 {
     if (fd >= 0)
     {
         int   res;
         Errno lastError;
         do
         {
             res       = Flock(fd, specificFlag ?? (lockFile ? FlockOperation.LOCK_EX : FlockOperation.LOCK_UN));
             lastError = Stdlib.GetLastError();
         }while(res != 0 && lastError == Errno.EINTR);
         // if can't get lock ...
         return(res == 0);
     }
     return(false);
 }
コード例 #17
0
 public bool Unlink()
 {
     lock (_syncObject)
     {
         if (Syscall.unlink(_name) == -1)
         {
             Errno errno = Stdlib.GetLastError();
             if (errno == Errno.ENOENT)
             {
                 return(false);
             }
             throw new NativeException((int)errno);
         }
         return(true);
     }
 }
コード例 #18
0
ファイル: EPollQueue.cs プロジェクト: jmptrader/EventCore
        public int Execute(int ms = 500)
        {
            int events = Syscall.epoll_wait(_epoll, _events, _events.Length, ms);

            if (events == -1)
            {
                Errno error = Stdlib.GetLastError();
                if (error != Errno.EINTR)
                {
                    throw new InvalidOperationException(String.Format("Error {0} occured while waiting for an event",
                                                                      error));
                }
            }

            return(events);
        }
コード例 #19
0
ファイル: EpollHandler.cs プロジェクト: obender12/hl18
        // can be called in the context of a worker thread
        public int OnWriteReady()
        {
            if (state != EState.Writing)
            {
                //Log.Error("Writing in state " + state);
                return(0);
            }
            Log.Epoll("[{0}] Writing {1} bytes from {2}", socketHandle,
                      ResponseTotalLength - totalWritten, ResponseStart + totalWritten);
            var written = Syscall.write(socketHandle,
                                        IntPtr.Add(bufferPtr, ResponseStart + totalWritten),
                                        (ulong)(ResponseTotalLength - totalWritten));

            Log.Epoll("[{0}] write() returned {1}", socketHandle, written);

            if (written < 0)
            {
                var errno = Stdlib.GetLastError();
                if (errno != 0 && errno != Errno.EAGAIN)
                {
                    Log.Error("[{0}] write() socket error {1}", socketHandle, errno);
                    return(-1); // waiting for the socket to be detached/closed
                }
                return(0);
            }
            if (written == 0)
            {
                Log.Epoll("[{0}] peer closed connection", socketHandle);
                // waiting for the socket to be detached/closed
                return(0);
            }
            Log.Epoll("[{0}] Written {1} bytes", socketHandle, written);
            totalWritten += (int)written;
            if (totalWritten < ResponseTotalLength)
            {
                // not all was written, try again
            }
            else
            {
                //Console.Write('>');
                Log.Epoll("[{0}] Request processing complete!", socketHandle);
                Stats.ReportContextTime(ContextType, Stats.Watch.Elapsed - processingStarted);
                processingStarted = new TimeSpan();
                setReading();
            }
            return(0);
        }
コード例 #20
0
 public void SetProcessName(string name)
 {
     if (OSName == "Linux")
     {
         if (prctl(15 /* PR_SET_NAME */, Encoding.ASCII.GetBytes(name + "\0"),
                   IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0)
         {
             throw new ApplicationException("Error setting process name: " +
                                            Stdlib.GetLastError());
         }
     }
     else if (OSName == "FreeBSD")         // XXX: I'm not sure this is right
     {
         setproctitle(Encoding.ASCII.GetBytes("%s\0"),
                      Encoding.ASCII.GetBytes(name + "\0"));
     }
 }
コード例 #21
0
        protected override unsafe Errno OnReadHandle(string path, OpenedPathInfo info, byte[] buf,
                                                     long offset, out int bytesRead)
        {
            int r;

            fixed(byte *pb = buf)
            {
                r = bytesRead = (int)Syscall.pread((int)info.Handle,
                                                   pb, (ulong)buf.Length, offset);
            }

            if (r == -1)
            {
                return(Stdlib.GetLastError());
            }
            return(0);
        }
コード例 #22
0
        public override void GetExtendedAttribute(string path, string name, byte[] value, out int bytesWritten)
        {
            var encPath = FileSystem.Path.GetEncryptedPath(path, true);

            bytesWritten = (int)Syscall.lgetxattr(encPath.GetPath(_source), name, value, (ulong)(value?.Length ?? 0));
            if (bytesWritten != -1)
            {
                return;
            }

            var err = Stdlib.GetLastError();

            if (err != Errno.ENODATA)
            {
                throw new NativeException((int)err);
            }
        }
コード例 #23
0
        public virtual unsafe Errno WriteHandle(string path, OpenedPathInfo info,
                                                byte[] buf, long offset, out int bytesWritten)
        {
            int r;

            fixed(byte *pb = buf)
            {
                r = bytesWritten = (int)Syscall.pwrite((int)info.Handle,
                                                       pb, (ulong)buf.Length, offset);
            }

            if (r == -1)
            {
                return(Stdlib.GetLastError());
            }
            return(0);
        }
コード例 #24
0
        public static string GetCurrentDirectory()
        {
            StringBuilder stringBuilder = new StringBuilder(16);
            IntPtr        zero          = IntPtr.Zero;

            do
            {
                StringBuilder capacity = stringBuilder;
                capacity.Capacity = capacity.Capacity * 2;
                zero = Syscall.getcwd(stringBuilder, (ulong)stringBuilder.Capacity);
            }while (zero == IntPtr.Zero && Stdlib.GetLastError() == Errno.ERANGE);
            if (zero == IntPtr.Zero)
            {
                UnixMarshal.ThrowExceptionForLastError();
            }
            return(stringBuilder.ToString());
        }
コード例 #25
0
        private static string strerror_r(Errno errno)
        {
            StringBuilder stringBuilder = new StringBuilder(16);
            int           num           = 0;

            do
            {
                StringBuilder capacity = stringBuilder;
                capacity.Capacity = capacity.Capacity * 2;
                num = Syscall.strerror_r(errno, stringBuilder);
            }while (num == -1 && Stdlib.GetLastError() == Errno.ERANGE);
            if (num != -1)
            {
                return(stringBuilder.ToString());
            }
            return(string.Concat("** Unknown error code: ", (int)errno, "**"));
        }
コード例 #26
0
        private static Errno ProcessFile(string path, OpenFlags flags, FdCb cb)
        {
            int fd = Syscall.open(path, flags);

            if (fd == -1)
            {
                return(Stdlib.GetLastError());
            }
            int   r   = cb(fd);
            Errno res = 0;

            if (r == -1)
            {
                res = Stdlib.GetLastError();
            }
            Syscall.close(fd);
            return(res);
        }
コード例 #27
0
        /// <inheritdoc />
        public void HandleWrite(string filePath)
        {
            //set executable bit every time, don't want people calling me when their uploaded "sl" binary doesn't work
            if (Syscall.stat(filePath, out var stat) != 0)
            {
                throw new UnixIOException(Stdlib.GetLastError());
            }

            if (stat.st_mode.HasFlag(FilePermissions.S_IXUSR))
            {
                return;
            }

            if (Syscall.chmod(filePath, stat.st_mode | FilePermissions.S_IXUSR) != 0)
            {
                throw new UnixIOException(Stdlib.GetLastError());
            }
        }
コード例 #28
0
        public bool Update(int fd, EpollEvents flags)
        {
            var ev = new EpollEvent()
            {
                events = flags,
                u32    = (uint)fd
            };

            Log.Epoll("[{0}] EPOLL_CTL_MOD({1})", fd, flags);
            var r = Syscall.epoll_ctl(epfd, EpollOp.EPOLL_CTL_MOD, fd, ref ev);

            if (r != 0)
            {
                Log.Error($"Call to epoll_ctl(MOD) failed with code {r}: {Stdlib.GetLastError()}");
                return(false);
            }
            return(true);
        }
コード例 #29
0
ファイル: DiskProvider.cs プロジェクト: nimeshjm/Sonarr
        private void SetOwner(string path, string user, string group)
        {
            if (string.IsNullOrWhiteSpace(user) && string.IsNullOrWhiteSpace(group))
            {
                Logger.Debug("User and Group for chown not configured, skipping chown.");
                return;
            }

            var userId  = GetUserId(user);
            var groupId = GetGroupId(group);

            if (Syscall.chown(path, userId, groupId) < 0)
            {
                var error = Stdlib.GetLastError();

                throw new LinuxPermissionsException("Error setting file owner and/or group: " + error);
            }
        }
コード例 #30
0
        public virtual Errno SynchronizeHandle(string path, OpenedPathInfo info, bool onlyUserData)
        {
            int r;

            if (onlyUserData)
            {
                r = Syscall.fdatasync((int)info.Handle);
            }
            else
            {
                r = Syscall.fsync((int)info.Handle);
            }
            if (r == -1)
            {
                return(Stdlib.GetLastError());
            }
            return(0);
        }