} // End Function Unmount public static string find_unused_loop_device() { string dev; int fd; Mono.Unix.Native.Stat statbuf; loop_info loopinfo = new loop_info(); loop_info64 lo64 = new loop_info64(); for (int i = 0; i <= 7; i++) { dev = "/dev/loop" + i.ToString(); if (System.Convert.ToBoolean(Mono.Unix.Native.Syscall.stat(dev, out statbuf)) == (false && S_ISBLK((int)statbuf.st_mode))) { if ((fd = Mono.Unix.Native.Syscall.open(dev, Mono.Unix.Native.OpenFlags.O_RDONLY)) >= 0) { // This block was commented out initially if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS64, ref lo64) == 0) { if (Mono.Unix.Native.Syscall.GetLastError() == Mono.Unix.Native.Errno.ENXIO) { // probably free Mono.Unix.Native.Syscall.close(fd); return(dev); } } if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS, ref loopinfo) != 0) { // http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/include/asm-generic/errno-base.h#L9 // ENXIO - No such device or address // The device accessed by a command is physically not present, // or the address of the device is not present if (Mono.Unix.Native.Syscall.GetLastError() == Mono.Unix.Native.Errno.ENXIO) { // that means the device is most-likely free Mono.Unix.Native.Syscall.close(fd); return(dev); } } // End if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS, ref loopinfo) != 0) Mono.Unix.Native.Syscall.close(fd); } // End if ((fd = UnsafeNativeMethods.open(dev, OpenFlags.O_RDONLY)) >= 0) } // End if (System.Convert.ToBoolean(Mono.Unix.Native.Syscall.stat(dev, out statbuf)) == (false && S_ISBLK((int)statbuf.st_mode))) } // Next i return(null); } // End Function find_unused_loop_device
} // End Function loopfile_from_sysfs public static string loopdev_get_loopfile(string device) { string res = loopfile_from_sysfs(device); if (res == null) { loop_info lo = new loop_info(); loop_info64 lo64 = new loop_info64(); int fd; if ((fd = Mono.Unix.Native.Syscall.open(device, Mono.Unix.Native.OpenFlags.O_RDONLY)) < 0) { return(null); } if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS64, ref lo64) == 0) { //lo64.lo_file_name[LO_NAME_SIZE-2] = '*'; //lo64.lo_file_name[LO_NAME_SIZE-1] = 0; //res = strdup((char *) lo64.lo_file_name); res = lo64.lo_file_name; Console.WriteLine("LOOP_GET_STATUS64"); } else if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS, ref lo) == 0) { //lo.lo_name[LO_NAME_SIZE-2] = '*'; //lo.lo_name[LO_NAME_SIZE-1] = 0; //res = strdup((char *) lo.lo_name); res = lo.lo_name; Console.WriteLine("LOOP_GET_STATUS"); } Mono.Unix.Native.Syscall.close(fd); } // End if (res == null) return(res); } // End Function loopdev_get_loopfile
} // End Function loopfile_from_sysfs private static string loopdev_get_loopfile(string device) { string res = loopfile_from_sysfs(device); if (res == null) { loop_info lo = new loop_info(); loop_info64 lo64 = new loop_info64(); int fd; if ((fd = Mono.Unix.Native.Syscall.open(device, Mono.Unix.Native.OpenFlags.O_RDONLY)) < 0) { return(null); } if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS64, ref lo64) == 0) { //lo64.lo_file_name[LO_NAME_SIZE-2] = '*'; //lo64.lo_file_name[LO_NAME_SIZE-1] = 0; //res = strdup((char *) lo64.lo_file_name); res = lo64.lo_file_name; } else if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS, ref lo) == 0) { //lo.lo_name[LO_NAME_SIZE-2] = '*'; //lo.lo_name[LO_NAME_SIZE-1] = 0; //res = strdup((char *) lo.lo_name); res = lo.lo_name; Logger.Append(P2PBackup.Common.Severity.TRIVIA, "Could not use LOOP_GET_STATUS64, defaulted to LOOP_GET_STATUS"); } Mono.Unix.Native.Syscall.close(fd); } // End if (res == null) return(res); } // End Function loopdev_get_loopfile
public static extern int ioctl(int d, int request, ref loop_info data);
} // End Function find_unused_loop_device public static int set_loop(string device, string file, int offset, ref int loopro) { loop_info loopinfo = new loop_info(); int fd = 0, ffd = 0; Mono.Unix.Native.OpenFlags mode; mode = loopro != 0 ? Mono.Unix.Native.OpenFlags.O_RDONLY : Mono.Unix.Native.OpenFlags.O_RDWR; if ( ( ffd = Mono.Unix.Native.Syscall.open(file, mode) ) < 0 && ( (!System.Convert.ToBoolean((int)loopro)) && ( Mono.Unix.Native.Syscall.GetLastError() != Mono.Unix.Native.Errno.EROFS || (ffd = Mono.Unix.Native.Syscall.open(file, mode = Mono.Unix.Native.OpenFlags.O_RDONLY)) < 0 ) ) ) // if { Console.WriteLine("Error: file: " + file); //perror_msg("%s", file); return(1); } // End if if ((fd = Mono.Unix.Native.Syscall.open(device, mode)) < 0) { Mono.Unix.Native.Syscall.close(ffd); Console.WriteLine("Error: device: " + device); //perror_msg("%s", device); return(1); } loopro = System.Convert.ToInt32(mode == Mono.Unix.Native.OpenFlags.O_RDONLY); //memset(&loopinfo, 0, sizeof(loopinfo)); //safe_strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); //strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); loopinfo.lo_name = string.IsNullOrEmpty(file) ? null : file.Substring(0, Math.Min(file.Length, LO_NAME_SIZE)); loopinfo.lo_offset = offset; loopinfo.lo_encrypt_key_size = 0; if (UnsafeNativeMethods.ioctl(fd, LOOP_SET_FD, ffd) < 0) { Console.WriteLine("ioctl: LOOP_SET_FD"); //perror_msg("ioctl: LOOP_SET_FD"); Mono.Unix.Native.Syscall.close(fd); Mono.Unix.Native.Syscall.close(ffd); return(1); } if (UnsafeNativeMethods.ioctl(fd, LOOP_SET_STATUS, ref loopinfo) < 0) { int ro = 0; UnsafeNativeMethods.ioctl(fd, LOOP_CLR_FD, ref ro); //perror_msg("ioctl: LOOP_SET_STATUS"); Console.WriteLine("ioctl: LOOP_SET_STATUS"); Mono.Unix.Native.Syscall.close(fd); Mono.Unix.Native.Syscall.close(ffd); return(1); } Mono.Unix.Native.Syscall.close(fd); Mono.Unix.Native.Syscall.close(ffd); return(0); } // End Function set_loop
} // End Function find_unused_loop_device private int set_loop(string device, string file, int offset, ref int loopro) { loop_info loopinfo = new loop_info(); int fd = 0, ffd = 0; Mono.Unix.Native.OpenFlags mode; mode = loopro != 0 ? Mono.Unix.Native.OpenFlags.O_RDONLY : Mono.Unix.Native.OpenFlags.O_RDWR; if ( ( ffd = Mono.Unix.Native.Syscall.open(file, mode) ) < 0 && ( (!System.Convert.ToBoolean((int)loopro)) && ( Mono.Unix.Native.Syscall.GetLastError() != Mono.Unix.Native.Errno.EROFS || (ffd = Mono.Unix.Native.Syscall.open(file, mode = Mono.Unix.Native.OpenFlags.O_RDONLY)) < 0 ) ) ) // if { throw new Exception("Error opening file '" + file + "' : " + ffd); } // End if if ((fd = Mono.Unix.Native.Syscall.open(device, mode)) < 0) { Mono.Unix.Native.Syscall.close(ffd); throw new Exception("Error opening device '" + device + "' : " + fd); } loopro = System.Convert.ToInt32(mode == Mono.Unix.Native.OpenFlags.O_RDONLY); //memset(&loopinfo, 0, sizeof(loopinfo)); //safe_strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); //strncpy(loopinfo.lo_name, file, LO_NAME_SIZE); loopinfo.lo_name = string.IsNullOrEmpty(file) ? null : file.Substring(0, Math.Min(file.Length, LO_NAME_SIZE)); loopinfo.lo_offset = offset; loopinfo.lo_encrypt_key_size = 0; loopinfo.lo_flags = (int)LoopFlags.LO_FLAGS_PARTSCAN; int retCode = UnsafeNativeMethods.ioctl(fd, LOOP_SET_FD, ffd); if (retCode < 0) { Mono.Unix.Native.Syscall.close(fd); Mono.Unix.Native.Syscall.close(ffd); throw new Exception("Error calling LOOP_SET_FD ioctl() : " + retCode); } retCode = UnsafeNativeMethods.ioctl(fd, LOOP_SET_STATUS, ref loopinfo); if (retCode < 0) { int ro = 0; UnsafeNativeMethods.ioctl(fd, LOOP_CLR_FD, ref ro); Mono.Unix.Native.Syscall.close(fd); Mono.Unix.Native.Syscall.close(ffd); throw new Exception("Error calling LOOP_SET_STATUS ioctl() : " + retCode); } Mono.Unix.Native.Syscall.close(fd); Mono.Unix.Native.Syscall.close(ffd); return(0); } // End Function set_loop