Linux下简单的mount命令实现(自动识别文件系统类型)
来源:互联网 发布:知乎 english in use 编辑:程序博客网 时间:2024/06/05 22:38
背景简述
mount()/umount()为Linux下挂载和卸载磁盘分区的系统调用,函数原型分别如下:
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data);int umount(const char *target);
mount()的filesystemtype这个参数需要填入需要挂载的磁盘分区的文件系统类型,比如需要挂载fat32,那么这个参数需要填写为“vfat”,分区文件系统类型为ext2,需要填写为“ext2”;如果挂载成功,返回0,挂载失败,返回-1;
所以,这就需要我们获取当前要挂载的磁盘分区的文件系统类型;在shell上我们可以通过fdisk /dev/sda 这样类似的命令,然后敲p打印出现当前的磁盘分区信息,但是如果想直接通过函数调用的方式获取(非system()系统调用),还得另外找办法;
hexdump读取分区信息
我们利用hexdump这个工具,分别读取ext2/fat32/ntfs分区的信息,如下方法:
hexdump读fat32分区:
# hexdump -C -n 256 sda100000000 eb fe 90 4d 53 44 4f 53 35 2e 30 00 02 10 20 00 |...MSDOS5.0... .|00000010 02 00 00 00 00 f8 00 00 3f 00 ff 00 00 00 00 00 |........?.......|00000020 e0 d7 d2 01 54 3a 00 00 00 00 00 00 02 00 00 00 |....T:..........|00000030 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|00000040 00 01 29 76 6d 01 00 4e 4f 20 4e 41 4d 45 20 20 |..)vm..NO NAME |00000050 20 20 46 41 54 33 32 20 20 20 00 00 00 00 00 00 | FAT32 ......|00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
有看到0x52 Offset开始的位置有字符串“FAT32”;
hexdump读ntfs分区:
# hexdump -C -n 256 /dev/sda200000000 eb 52 90 4e 54 46 53 20 20 20 20 00 02 08 00 00 |.R.NTFS .....|00000010 00 00 00 00 00 f8 00 00 3f 00 ff 00 20 00 00 00 |........?... ...|00000020 00 00 00 00 80 00 00 00 df 3f 19 01 00 00 00 00 |.........?......|00000030 00 00 0c 00 00 00 00 00 02 00 00 00 00 00 00 00 |................|00000040 f6 00 00 00 01 00 00 00 6d 8e f9 6c b3 f9 6c 96 |........m..l..l.|00000050 00 00 00 00 fa 33 c0 8e d0 bc 00 7c fb 68 c0 07 |.....3.....|.h..|00000060 1f 1e 68 66 00 cb 88 16 0e 00 66 81 3e 03 00 4e |..hf......f.>..N|00000070 54 46 53 75 15 b4 41 bb aa 55 cd 13 72 0c 81 fb |TFSu..A..U..r...|00000080 55 aa 75 06 f7 c1 01 00 75 03 e9 dd 00 1e 83 ec |U.u.....u.......|00000090 18 68 1a 00 b4 48 8a 16 0e 00 8b f4 16 1f cd 13 |.h...H..........|000000a0 9f 83 c4 18 9e 58 1f 72 e1 3b 06 0b 00 75 db a3 |.....X.r.;...u..|000000b0 0f 00 c1 2e 0f 00 04 1e 5a 33 db b9 00 20 2b c8 |........Z3... +.|000000c0 66 ff 06 11 00 03 16 0f 00 8e c2 ff 06 16 00 e8 |f...............|000000d0 4b 00 2b c8 77 ef b8 00 bb cd 1a 66 23 c0 75 2d |K.+.w......f#.u-|000000e0 66 81 fb 54 43 50 41 75 24 81 f9 02 01 72 1e 16 |f..TCPAu$....r..|000000f0 68 07 bb 16 68 70 0e 16 68 09 00 66 53 66 53 66 |h...hp..h..fSfSf|
在Offset ox3处有发现“NTFS”这样的字符串;
ext2/ext3格式不太一样,直接读前面256bytes读不到有特别能说明文件系统类型的字符串。有参考Linux 文件系统的 Superblock, Inode, Dentry 和 File这篇blog,这篇blog里面有详细描述Linux下ext2的Inode和Block,其中有superblock的说明,结构体类型如下:
struct ext3_super_block {/*00*/ __u32 s_inodes_count; /* inodes 计数 */__u32 s_blocks_count; /* blocks 计数 */__u32 s_r_blocks_count; /* 保留的 blocks 计数 */__u32 s_free_blocks_count; /* 空闲的 blocks 计数 *//*10*/ __u32 s_free_inodes_count; /* 空闲的 inodes 计数 */__u32 s_first_data_block; /* 第一个数据 block */__u32 s_log_block_size; /* block 的大小 */__s32 s_log_frag_size; /* 可以忽略 *//*20*/ __u32 s_blocks_per_group; /* 每 block group 的 block 数量 */__u32 s_frags_per_group; /* 可以忽略 */__u32 s_inodes_per_group; /* 每 block group 的 inode 数量 */__u32 s_mtime; /* Mount time *//*30*/ __u32 s_wtime; /* Write time */__u16 s_mnt_count; /* Mount count */__s16 s_max_mnt_count; /* Maximal mount count */__u16 s_magic; /* Magic 签名 */__u16 s_state; /* File system state */__u16 s_errors; /* Behaviour when detecting errors */__u16 s_minor_rev_level; /* minor revision level *//*40*/ __u32 s_lastcheck; /* time of last check */__u32 s_checkinterval; /* max. time between checks */__u32 s_creator_os; /* 可以忽略 */__u32 s_rev_level; /* Revision level *//*50*/ __u16 s_def_resuid; /* Default uid for reserved blocks */__u16 s_def_resgid; /* Default gid for reserved blocks */__u32 s_first_ino; /* First non-reserved inode */__u16 s_inode_size; /* size of inode structure */__u16 s_block_group_nr; /* block group # of this superblock */__u32 s_feature_compat; /* compatible feature set *//*60*/ __u32 s_feature_incompat; /* incompatible feature set */__u32 s_feature_ro_compat; /* readonly-compatible feature set *//*68*/ __u8 s_uuid[16]; /* 128-bit uuid for volume *//*78*/ char s_volume_name[16]; /* volume name *//*88*/ char s_last_mounted[64]; /* directory where last mounted *//*C8*/ __u32 s_algorithm_usage_bitmap; /* 可以忽略 */__u8 s_prealloc_blocks; /* 可以忽略 */__u8 s_prealloc_dir_blocks; /* 可以忽略 */__u16 s_padding1; /* 可以忽略 *//*D0*/ __u8 s_journal_uuid[16]; /* uuid of journal superblock *//*E0*/ __u32 s_journal_inum; /* 日志文件的 inode 号数 */__u32 s_journal_dev; /* 日志文件的设备号 */__u32 s_last_orphan; /* start of list of inodes to delete *//*EC*/ __u32 s_reserved[197]; /* 可以忽略 */};
其中s_magic在ext2/ext3上固定为0xEF53。这个superblock放在分区的superblock1上(一个superblock大小为0x400bytes),所以可以通过s_magic去判定是否是ext2或者ext3,通过hexdump打印ext2的superblock1如下:
# hexdump -C -n 1024 -s 1024 sda300000400 40 ce 08 00 fc 27 23 00 ff c1 01 00 71 9a 22 00 |@....'#.....q.".|00000410 33 ce 08 00 00 00 00 00 02 00 00 00 02 00 00 00 |3...............|00000420 00 80 00 00 00 80 00 00 c0 1f 00 00 78 40 ca 59 |............x@.Y|00000430 5d 00 00 00 05 00 25 00 53 ef 00 00 01 00 00 00 |].....%.S.......|00000440 06 04 00 00 00 4e ed 00 00 00 00 00 01 00 00 00 |.....N..........|00000450 00 00 00 00 0b 00 00 00 00 01 00 00 20 00 00 00 |............ ...|00000460 02 00 00 00 01 00 00 00 14 1f 7f da 41 8f 46 fb |............A.F.|00000470 81 ef 72 2e 2f fa db 25 00 00 00 00 00 00 00 00 |..r./..%........|00000480 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*000004e0 00 00 00 00 00 00 00 00 00 00 00 00 9d f7 68 b5 |..............h.|000004f0 f1 14 44 86 93 ca 80 84 aa 93 05 41 01 00 00 00 |..D........A....|00000500 00 00 00 00 00 00 00 00 06 04 00 00 00 00 00 00 |................|00000510 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*00000550 00 00 00 00 00 00 00 00 00 00 00 00 1c 00 1c 00 |................|00000560 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|00000570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
C实现获取文件系统类型
根据上面的实验结果,所实现的获取分区文件系统函数如下:
typedef enum{ FS_NTFS, FS_FAT32, FS_EXT2, FS_ERROR_TYPE,}FILE_SYS_TYPE;/** * [_getFSType get the filesystem type of partion] * @param devFD [the handle of usb partition device from open()] * @return [the filesystem type] */static FILE_SYS_TYPE _getFSType(int devFD){ unsigned char tmpBuffer[0x400]; unsigned char* pOffset = NULL; unsigned int readSize = 0; pOffset = &tmpBuffer[0]; memset(pOffset, 0x00, 0x400); //read the tag data for ntfs/fat32 readSize = read(devFD, pOffset, 0x100); if(!readSize) { printf("read device file failed!\n"); return FS_ERROR_TYPE; } if(!memcmp((const void*)(pOffset+0x52), (const void*)"FAT32", 5))//th offset with 0x52 is fat32 tag; { printf("filesystem:fat32!\n"); return FS_FAT32; } else if(!memcmp((const void*)(pOffset+0x3), (const void*)"NTFS", 4))//the offset with 0x3 is ntfs tag; { printf("filesystem:ntfs!\n"); return FS_NTFS; } else { memset(pOffset, 0x00, 0x400); lseek(devFD,0x400, SEEK_SET); //seek to superblock1; readSize = read(devFD, pOffset, 0x400);//read the superblock1 to buffer; if(!readSize) { printf("read1 device file failed!\n"); return FS_ERROR_TYPE; } pOffset = pOffset+0x38; //the offset 0x438 is the tag of ext2:0x53 0xef; if((pOffset[0] == 0x53) && (pOffset[1] == 0xef)) { printf("filesystem:ext2 or ext3!\n"); return FS_EXT2; } else { printf("the offset 0x438 vaule is:0x%x 0x%x!\n", pOffset[0], pOffset[1]); } } printf("Unknown filesystem type!\n"); return FS_ERROR_TYPE;}
上面的函数要求传入分区对应的handle(用open()函数得到),然后返回文件系统类型;
测试函数
测试函数代码auto_mount.c如下:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <fcntl.h>/** * [main auto mount usb partions] * @param argc [the arguments number] * @param argv [the arguments pointer] * @return [the error code] */int main(int argc, char *argv[]){ char devPath[512]; char mountPath[512]; int devFD = 0; int ret = -1; FILE_SYS_TYPE fsType = FS_ERROR_TYPE; if(argc != 3) { printf("error paramter!\n"); return -1; } snprintf(devPath,511,"%s", argv[1]); snprintf(mountPath,511,"%s", argv[2]); printf("devPath:%s, mountPath:%s\n", devPath, mountPath); devFD = open(devPath, O_RDONLY); if(!devFD) { printf("Open device failed!\n"); return -1; } fsType = _getFSType(devFD); printf("fs type:%d\n", fsType); switch(fsType) { case FS_EXT2: ret=mount((const char*)devPath, (const char*)mountPath, (const char*)"ext2", 0, NULL); break; case FS_NTFS: ret=mount((const char*)devPath, (const char*)mountPath, (const char*)"ntfs3g", 0, NULL); break; case FS_FAT32: ret=mount((const char*)devPath, (const char*)mountPath, (const char*)"vfat", 0, NULL); break; default: printf("Unknown filesystem type!\n"); } printf("mount result:%d\n", ret); close(devFD); return 0;}
测试函数可以如下方法编译:
gcc auto_mount.c -o auto_mount;
在sudo chmod +x auto_mount增加可执行权限后,可以如下方法运行:
./auto_mount /dev/sda1 /mnt/sda1; //将/dev/sda1这个设备mount到/mnt/sda1这个目录;
- Linux下简单的mount命令实现(自动识别文件系统类型)
- linux下mount命令使用详解---linux挂载光盘等文件系统的命令
- linux文件系统类型及mount
- linux 下mount命令
- Linux下的mount命令使用方法(转载)
- linux下mount命令的用法
- linux下的mount挂载命令
- 《一个操作系统的实现》mount错误解决办法(mount 您必须指定文件系统的类型
- 《一个操作系统的实现》mount错误解决办法(mount 您必须指定文件系统的类型
- 一个操作系统的实现--mount错误解决办法--mount 您必须指定文件系统的类型
- 从内核的角度看linux文件系统以及一些类似于mount命令的原理(未完)
- linux vfs 解析 之 mount 文件系统 (下)
- linux vfs 解析 之 mount 文件系统 (下)
- linux文件系统命令(3)---mount和umount
- Linux的mount命令
- 查看文件系统类型的Linux命令
- 查看文件系统类型的Linux命令
- 查看文件系统类型的Linux命令
- 《程序设计入门—Java语言.翁恺》第三周编程作业(1)-奇偶个数
- Recovery启动流程(1)--- 应用层到开机进入recovery详解
- 菱形
- Fair Game
- 【学术篇】一些水的不行的dp
- Linux下简单的mount命令实现(自动识别文件系统类型)
- 51nod 1290 Counting Diff Pairs(莫队+树状数组)
- WebGL快速入门及实例(一)
- golang笔记:游戏中排行榜的实现
- java---Buffered
- ISO/IEC 14496 文档内容 简介
- css3基础
- 如何学习spring入门知识点.
- jquery的封装ajax的get请求