С / С++ / С#: методические указания делать "гора -"
Вопрос:
В C / C++/C#. (Мне это нужно для C#, но C и C++ тоже отлично).
Как я могу сделать mount-a на Linux. Я имею в виду программно, Без запуска процесса, подобного
system("mount -a");
Редактировать:
Обратите внимание на букву "А".
Мой вопрос на самом деле не о том, как установить точку монтирования.
Речь идет о том, как монтировать все точки монтирования в файле /etc/fstab.
Это означает разбор файла, извлечение точек монтирования, проверку, если они уже смонтированы, и только если нет уже установлен, крепление...
3 ответа:
getmntent
может помочь вам прочитать/etc/fstab
(а затем использовать функцию mount в других ответах).
Проверьте справочную страницу, введя
man 2 mount
. Он говорит о системном вызове, который может избежать фактического использования system ():#include <sys/mount.h> int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data);
@Игнасио Васкес-Абрамс: О вашем "нет способа выполнить это в C#"...
Доказательство того, что вы неправы противоречием:
Приведенный ниже код способен делать то же самое, что и
(apt-get install jfsutils) dd if=/dev/zero of=jfs.dsk bs=1048576 count=150 mkfs.jfs -O jfs.dsk mkdir -p /mnt/jfs mount /volumes/jfs.dsk /mnt/jfs -t jfs -o loop umount /mnt/jfs/
Код:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Syscalls { public class Linux { // apt-get source util-linux // ./mount/loop.h // ./mount/mount.c // ./mount/lomount.c // ./include/linux_version.h // ./lib/linux_version.c // ./include/linux_reboot.h protected const int LOOP_SET_FD = 0x4C00; protected const int LOOP_CLR_FD = 0x4C01; protected const int LOOP_GET_STATUS = 0x4C03; protected const int LOOP_SET_STATUS = 0x4C02; protected const int LOOP_GET_STATUS64 = 0x4C05; protected const int LOOP_SET_STATUS64 = 0x4C04; protected const int LO_NAME_SIZE = 64; protected const int LO_KEY_SIZE = 32; protected const int PATH_MAX = 4096; // MS_RELATIME //(default for Linux >= 2.6.30) // MS_STRICTATIME //(default for Linux < 2.6.30) // http://harmattan-dev.nokia.com/docs/library/html/manpages/headers/sys/mount.html public enum MountFlags : ulong { MS_RDONLY = 1, // Mount read-only. MS_NOSUID = 2, // Ignore suid and sgid bits. MS_NODEV = 4, // Disallow access to device special files. MS_NOEXEC = 8, // Disallow program execution. MS_SYNCHRONOUS = 16, // Writes are synced at once. MS_REMOUNT = 32, // Alter flags of a mounted FS. MS_MANDLOCK = 64, // Allow mandatory locks on an FS. S_WRITE = 128, // Write on file/directory/symlink. S_APPEND = 256, // Append-only file. S_IMMUTABLE = 512, // Immutable file. MS_NOATIME = 1024, // Do not update access times. MS_NODIRATIME = 2048, // Do not update directory access times. MS_BIND = 4096, // Bind directory at different place. }; // End Enum MountFlags : ulong /* // http://unix.superglobalmegacorp.com/Net2/newsrc/sys/fcntl.h.html [Flags] protected enum OpenFlags : int { // open-only flags O_RDONLY = 0x0000, // open for reading only O_WRONLY = 0x0001, // open for writing only O_RDWR = 0x0002, // open for reading and writing O_ACCMODE = 0x0003, // mask for above modes //#ifdef KERNEL FREAD = 0x0001, FWRITE = 0x0002, //#endif O_NONBLOCK = 0x0004, // no delay O_APPEND = 0x0008, // set append mode //#ifndef _POSIX_SOURCE O_SHLOCK = 0x0010, // open with shared file lock O_EXLOCK = 0x0020, // open with exclusive file lock O_ASYNC = 0x0040, // signal pgrp when data ready O_FSYNC = 0x0080, // synchronous writes //#endif O_CREAT = 0x0200, // create if nonexistant O_TRUNC = 0x0400, // truncate to zero length O_EXCL = 0x0800, // error if already exists //#ifdef KERNEL FMARK = 0x1000, // mark during gc() FDEFER = 0x2000, // defer for next gc pass FHASLOCK = 0x4000 // descriptor holds advisory lock } // End Enum OpenFlags : int */ [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)] protected struct loop_info { public int lo_number; public System.UIntPtr lo_device; //my_dev_t lo_device; // my_dev_t: long unsigned int public System.UIntPtr lo_inode; //unsigned long lo_inode; public System.UIntPtr lo_rdevice; //my_dev_t lo_rdevice;// my_dev_t: long unsigned int public int lo_offset; public int lo_encrypt_type; public int lo_encrypt_key_size; public int lo_flags; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = LO_NAME_SIZE)] public string lo_name; //char lo_name[LO_NAME_SIZE]; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = LO_KEY_SIZE)] public string lo_encrypt_key; //unsigned char lo_encrypt_key[LO_KEY_SIZE]; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 2)] public System.UIntPtr[] lo_init; //unsigned long lo_init[2]; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 4)] public string reserved; //char reserved[4]; }; // End Struct loop_info protected struct loop_info64 { public System.UInt64 lo_device; public System.UInt64 lo_inode; public System.UInt64 lo_rdevice; public System.UInt64 lo_offset; public System.UInt64 lo_sizelimit; /* bytes, 0 == max available */ public System.UInt32 lo_number; public System.UInt32 lo_encrypt_type; public System.UInt32 lo_encrypt_key_size; public System.UInt32 lo_flags; // http://stackoverflow.com/questions/1725855/uint8-t-vs-unsigned-char [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = LO_NAME_SIZE)] public string lo_file_name; // uint8_t lo_file_name[LO_NAME_SIZE]; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = LO_NAME_SIZE)] public string lo_crypt_name; // uint8_t lo_crypt_name[LO_NAME_SIZE]; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = LO_KEY_SIZE)] public string lo_encrypt_key; // uint8_t lo_encrypt_key[LO_KEY_SIZE]; [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 2)] public System.UInt64[] lo_init; }; // End Struct loop_info64 // http://www.student.cs.uwaterloo.ca/~cs350/common/os161-src-html/kern_2include_2kern_2stat_8h.html protected static bool S_ISBLK(int mode) { const uint S_IFMT = 070000; const uint S_IFBLK = 050000; return (((mode) & S_IFMT) == S_IFBLK); } // End Function S_ISBLK public static int KERNEL_VERSION() { Mono.Unix.Native.Utsname unameres = new Mono.Unix.Native.Utsname(); Mono.Unix.Native.Syscall.uname(out unameres); System.Text.RegularExpressions.Match ma = System.Text.RegularExpressions.Regex.Match(unameres.release, @"(\d+).(\d+).(\d+)(-)?(\d+)?"); string strMajor = ma.Groups[1].Value; string strMinor = ma.Groups[2].Value; string strTiny = ma.Groups[3].Value; string strPatchlevel = ma.Groups[5].Value; int a = System.Convert.ToInt32(strMajor); int b = System.Convert.ToInt32(strMinor); int c = System.Convert.ToInt32(strTiny); return KERNEL_VERSION(a, b, c); } // End Function KERNEL_VERSION //# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) public static int KERNEL_VERSION(int a, int b, int c) { return (((a) << 16) + ((b) << 8) + (c)); } public static string CreateVirtualDisk(int iSize) { string strBaseDirectory = @"/volumes/"; string strFileName = System.Guid.NewGuid().ToString().Replace("-", "") + ".dsk"; string strFileNameAndPath = System.IO.Path.Combine(strBaseDirectory, strFileName); using (var fs = new System.IO.FileStream(strFileNameAndPath, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None)) { fs.SetLength(iSize); } // End Using fs return strFileNameAndPath; } // End Function CreateVirtualDisk // umount("/mnt/testdisk"); public static bool umount(string strMountPoint) { int status = UnsafeNativeMethods.umount(strMountPoint); if (status == 0) Console.WriteLine("Successfully unmounted device."); else Console.WriteLine("Unmount status: " + status.ToString()); if (status == 0) return true; return false; } // 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 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 public static int del_loop(string device) { int fd; if ((fd = Mono.Unix.Native.Syscall.open(device, Mono.Unix.Native.OpenFlags.O_RDONLY)) < 0) { //perror_msg("%s", device); Console.WriteLine("Error description: " + Mono.Unix.Native.Syscall.strerror(Mono.Unix.Native.Syscall.GetLastError())); return 0; } int r = 0; if (UnsafeNativeMethods.ioctl(fd, LOOP_CLR_FD, ref r) < 0) { //perror_msg("ioctl: LOOP_CLR_FD"); Console.WriteLine("ioctl: LOOP_CLR_FD\nError description: " + Mono.Unix.Native.Syscall.strerror(Mono.Unix.Native.Syscall.GetLastError())); return 0; } Mono.Unix.Native.Syscall.close(fd); Console.WriteLine("Successfully closed loop-device\n"); return 1; } // End Function del_loop public static bool mount(string strDevice, string strMountPoint, string strFsType) { return mount(strDevice, strMountPoint, strFsType, MountFlags.MS_NOATIME); } public static bool mount(string strDevice, string strMountPoint, string strFsType, MountFlags mflags) { return mount(strDevice, strMountPoint, strFsType, mflags, IntPtr.Zero); } // http://cboard.cprogramming.com/c-programming/126630-using-sys-mount-h-mounting-usb-thumb-drive.html // http://stackoverflow.com/questions/10458549/mount-usb-drive-in-linux-with-c // mount("/dev/loop1", "/mnt/testdisk", "vfat"); public static bool mount(string strDevice, string strMountPoint, string strFsType, MountFlags mflags, IntPtr options) { // http://linux.die.net/man/2/mount // MS_RDONLY // MS_RELATIME (default for Linux >= 2.6.30) // MS_STRICTATIME (default for Linux < 2.6.30) if (UnsafeNativeMethods.mount(strDevice, strMountPoint, strFsType, mflags, options) != 0) { Mono.Unix.Native.Errno errno = Mono.Unix.Native.Syscall.GetLastError(); if (errno == Mono.Unix.Native.Errno.EBUSY) { Console.WriteLine("Mountpoint busy"); } else { Console.WriteLine("Mount error: " + Mono.Unix.Native.Syscall.strerror(errno)); } return false; } else { Console.WriteLine("Successfully mounted device !"); } return true; ; } // End Function mount static class UnsafeNativeMethods { //string name = "Test"; //TypedReference tf = __makeref(name); //int c = VarSum(2, __arglist(__makeref(name))); // http://khason.net/blog/how-to-pinvoke-varargs-variable-arguments-in-c-or-hidden-junk-in-clr/ // //int rv = ioctl(2, 3, __arglist(5, 10)); [System.Runtime.InteropServices.DllImportAttribute("libc", EntryPoint = "ioctl", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)] public static extern int ioctl(int descriptor, int request, __arglist); [System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] public static extern int ioctl(int d, int request, int data); [System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] public static extern int ioctl(int d, int request, ref int data); [System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] public static extern int ioctl(int d, int request, ref loop_info data); [System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] public static extern int ioctl(int d, int request, ref loop_info64 data); //[System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] //public static extern int open([System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]string pathname, OpenFlags flags); //[System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] //public static extern int close(int fd); //[System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] //public static extern IntPtr read(int fd, IntPtr buffer, UIntPtr count); ///////unsafe public static extern IntPtr read(int fd, void* buffer, UIntPtr count); // http://linux.die.net/man/2/mount // http://www.kernel.org/doc/man-pages/online/pages/man2/mount.2.html [System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] private static extern int mount(string source, string target, string filesystemtype, UIntPtr mountflags, System.IntPtr data); //int mount(const char *source, const char *target, const char *filesystemtype, ulong mountflags, const void *data); public static int mount(string source, string target, string filesystemtype, MountFlags mountflags, System.IntPtr data) { System.UIntPtr p = new System.UIntPtr((ulong)mountflags); return mount(source, target, filesystemtype, p, data); } // End Function mount [System.Runtime.InteropServices.DllImport("libc", SetLastError = true)] public static extern int umount(string strMountPoint); // extern int umount (__const char *__special_file); } // End Class UnsafeNativeMethods public static void TryMount() { const bool SUCCESS = true; // int iReturnCode = Mono.Unix.Native.Syscall.system("mount -a"); // int iReturnCode = Mono.Unix.Native.Syscall.system("mount /volumes/jfs.dsk /mnt/jfs -t jfs -o loop"); // int iReturnCode = Mono.Unix.Native.Syscall.system("mkfs.jfs -O \"jfs.dsk\""); string strLoopDeviceToUse = find_unused_loop_device(); string strMountPoint = "/mnt/testdisk"; int ro = 0; set_loop(strLoopDeviceToUse, "/volumes/testdisk.dsk", 0, ref ro); string strLoopDeviceToUse2 = find_unused_loop_device(); bool status = false; int mountAttempts = 0; do { //status = mount("/dev/sda1", "/media/usb0", "vfat", MS_MGC_VAL | MS_NOSUID, ""); status = mount(strLoopDeviceToUse, strMountPoint, "vfat", MountFlags.MS_NOATIME); if (status != SUCCESS) System.Threading.Thread.Sleep(1000); mountAttempts++; } while (status != SUCCESS && mountAttempts < 3); } // End Sub TryMount // In gcc or g++, to show all of the macros that are defined for a given platform: // gcc -dM -E test.c // or // g++ -dM -E test.cpp // http://manual.cream.org/index.cgi/gnu_dev_major.3 // http://www.gnu.org/software/gnulib/coverage/usr/include/sys/sysmacros.h.gcov.frameset.html // http://en.wikipedia.org/wiki/C_data_types protected static uint gnu_dev_major(System.UInt64 __dev) { return (uint)((uint)(((__dev >> 8) & 0xfff)) | ((uint)(__dev >> 32) & ~0xfff)); } protected static uint gnu_dev_minor(System.UInt64 __dev) { return (uint)((uint)(__dev & 0xff) | ((uint)(__dev >> 12) & ~0xff)); } public static string loopfile_from_sysfs(string device) { string res = null; Mono.Unix.Native.Stat st; System.IntPtr f; //if (stat(device, &st) || !S_ISBLK(st.st_mode)) //if (System.Convert.ToBoolean(Mono.Unix.Native.Syscall.stat(device, out st)) || !S_ISBLK((int) st.st_mode)) // return null; Mono.Unix.Native.Syscall.stat(device, out st); const string _PATH_SYS_DEVBLOCK = "/sys/dev/block"; string strPath = string.Format("{0}/{1}:{2}/loop/backing_file", _PATH_SYS_DEVBLOCK, gnu_dev_major(st.st_rdev), gnu_dev_minor(st.st_rdev)); f = Mono.Unix.Native.Syscall.fopen(strPath, "r"); if (f == IntPtr.Zero) return null; Mono.Unix.Native.Syscall.fclose(f); res = System.IO.File.ReadAllText(strPath); strPath = null; return res; } // 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 public static void TryUnmount() { /* string strMountPoint = "/mnt/testdisk"; umount(strMountPoint); System.Threading.Thread.Sleep(1000); del_loop("/dev/loop2"); */ string xxx = loopdev_get_loopfile("/dev/loop0"); Console.WriteLine("xxx: " + xxx); } // kernel-support: // grep hfs /proc/filesystems // cat /proc/partitions // apt-get install hfsprogs // sudo modprobe hfsplus // dd if=/dev/zero of=hfsplus.dsk bs=1048576 count=150 // mkfs.hfsplus /volumes/hfsplus.dsk // mkfs.hfsplus hfsplus.dsk // apt-get install jfsutils // dd if=/dev/zero of=jfs.dsk bs=1048576 count=150 // mkfs.jfs -O jfs.dsk // mkdir -p /mnt/jfs // mount /volumes/jfs.dsk /mnt/jfs -t jfs -o loop // umount /mnt/jfs/ // mkdir -p /mnt/hfsplus // mount -t hfsplus /volumes/hfsplus.dsk /mnt/hfsplus/ -o loop // } // End Class Linux } // End Namespace Syscalls // http://ubuntuforums.org/showthread.php?t=135113 // http://stackoverflow.com/questions/7027151/call-expect-script-in-c-process // http://linux.die.net/man/1/expect // http://linux.die.net/man/3/libexpect // http://linuxcommand.org/man_pages/losetup8.html // losetup /dev/loop0 /file // losetup -d /dev/loop0 // http://linux.about.com/library/cmd/blcmdl8_losetup.htm
Чтобы перемонтировать его в fstab, вам нужно получить раздел uuid (blkid)