android usb挂载分析--ext*支持uid、gid等选项

来源:互联网 发布:mac ext4 读写 编辑:程序博客网 时间:2024/06/02 13:13

原址:http://blog.csdn.net/new_abc/article/details/7459299

同ntfs一样,Android默认的是不支持ext*格式的,可以自己把这些格式的支持加上去,但有一个问题,ext*不像fat那样挂载的时候支持uid、gid、fdmask等 参数,这会导致文件系统挂载上去后,发现还有一个问题,ext2,ext3,ext4的挂载上去后在应用中文件看不到,查了下原因是因为应用不能写u盘,说的具体点是应用的这个用户没有权限写u盘,我们看下fat挂载上去后的目录权限:

[plain] view plain copy
 print?
  1. ls -l  
  2. drwxr-xr-x root     system            1970-01-01 08:00 obb  
  3. drwxr-xr-x root     system            1970-01-01 08:00 asec  
  4. drwx------ root     root              1970-01-01 08:00 secure  
  5. d---rwxr-x system   sdcard_rw          2012-03-29 17:11 sdcard  

可以看到用户为systme,组为sdcard_rw但system的权限为0,组sdcard_rw的权限为7,可以读写,所以应用可以操作存储设备,这是因为在挂载fat格式的设备时mount的选项有uid=1000,gid=1015,fmask=702,dmask=702,1000在定义的是system,1015定义的是组sdcard_rw,fmask=702,dmask=702表示的是实际的权限与这个mask的~,所以:就有了上面的目录权限,只要是sdcard_rw组的用户都可以读写存储设备,但我在做其它格式的u盘挂载的时候,由于mount选项不支持,所以没有了这些选项的支持,导致挂载上去的目录是这样的:

[plain] view plain copy
 print?
  1. ls -l  
  2. drwxr-xr-x root     system            1970-01-01 08:00 obb  
  3. drwxr-xr-x root     system            1970-01-01 08:00 asec  
  4. drwx------ root     root              1970-01-01 08:00 secure  
  5. d rwxr-x --- root     root            2012-03-29 17:11 sdcard  

只有root用户才能写,所以应用进行写操作的时候会失败。开始用了一个很猥琐的方法,去解决这个问题,在mount上去后用chmod把sdcard这个目录的权限改为777 ,这样所有的用户对这个目录都有读写权限了,不过这好像感觉不太好,违背了android的权限管理,所以想办法搞成和fat挂载上去的权限一样,用了chown改变用户以及chgrp改变组,后面试了在mount的前面setgid改变组,不能使用setuid(1000),这样后没有权限mount了,这办法都试了,不过看了下效果还是不行,而且感觉做的很**,没办法,网上找了下,发现一个可以给内核打个补丁,使ext*打补丁能支持uid,gid选项,后面参照这个把mask的设置也加上去了,

[plain] view plain copy
 print?
  1. ls -l  
  2. drwxr-xr-x root     system            1970-01-01 08:00 obb  
  3. drwxr-xr-x root     system            1970-01-01 08:00 asec  
  4. drwx------ root     root              1970-01-01 08:00 secure  
  5. d---rwxr-x system   sdcard_rw          2012-03-29 17:11 sdcard  
  6. # cd sdcard  
  7. cd sdcard  
  8. # ls -l  
  9. ls -l  
  10. d---rwxr-x system   sdcard_rw          2012-03-29 17:04 lost+found  
  11. d---rwxr-x system   sdcard_rw          2012-03-29 17:07 test  
  12. drwxr-xr-x root     root              2012-03-29 17:11 LOST.DIR  
细心的读者可能发现,虽说挂载上去的文件权限已经uid、gid对了,但是新建出来的文件还是不对,所以这里还要针对这个问题修改一下内核,如果不修改的话,会导致应用安装不上去。

先看一下mount的步骤:

这里不去介绍这个系统调用的过程了,主要看到最后调用 了ext2_fill_super取填充超级块结构,而这里super结构中的s_fs_info正是针对具体文件系统的一些信息,我们的修改也主要在此

首先在ext2_sb_info结构中增加如下成员:

[plain] view plain copy
 print?
  1. uid_t s_uid; /* make all files appear to belong to this uid */  
  2. uid_t s_diskuid; /* write this uid to disk (if s_uid != 0) */  
  3. gid_t s_gid; /* make all files appear to belong to this gid */  
  4. gid_t s_diskgid; /* write this gid to disk (if s_gid != 0) */  
  5. unsigned short fs_fmask;  
  6. unsigned short fs_dmask;  
这里的s_diskuid和 s_diskgid这里暂时还有用到,不过也加进去了

在ext2.h 增加下面两个函数,用来进行uid,gid,mode的相应修改:

[cpp] view plain copy
 print?
  1. static inline mode_t ext2_make_mode(struct ext2_sb_info *ei, umode_t i_mode)  
  2. {  
  3.     umode_t     mode;  
  4.     if(S_ISDIR(i_mode) ||i_mode == 0)  
  5.     {  
  6.         mode =   (00777 & ~ei->fs_dmask) | S_IFDIR;  
  7.     }  
  8.     else  
  9.     {  
  10.         mode =   (00777 &~ei->fs_fmask) | S_IFREG;  
  11.     }  
  12.     return mode;  
  13. }  
  14. static inline void ext2_fill_inode(struct super_block *sb, struct inode *inode)  
  15. {  
  16.     if (EXT2_SB(sb)->fs_fmask  || EXT2_SB(sb)->fs_dmask) {  
  17.         inode->i_mode = ext2_make_mode(EXT2_SB(sb), inode->i_mode);  
  18.     }  
  19.     if (EXT2_SB(sb)->s_uid) {  
  20.         inode->i_uid = EXT2_SB(sb)->s_uid;  
  21.     }  
  22.     if (EXT2_SB(sb)->s_gid) {  
  23.         inode->i_gid = EXT2_SB(sb)->s_gid;  
  24.     }  
  25.     return;  
  26. }  

在fs/ext2/super.c中增加上面 ext2_sb_info结构中增加成员对应的解析选项:

[cpp] view plain copy
 print?
  1. enum {  
  2.    ...  
  3.    Opt_uid, Opt_diskuid, Opt_gid, Opt_diskgid,Opt_fmask, Opt_dmask,  
  4. };  

在tokens中增加相应的字符串映射:

[cpp] view plain copy
 print?
  1. static const match_table_t tokens = {  
  2.     ....  
  3.         {Opt_uid, "uid=%u"},  
  4.     {Opt_diskuid, "uid=%u:%u"},  
  5.     {Opt_gid, "gid=%u"},  
  6.     {Opt_diskgid, "gid=%u:%u"},  
  7.     {Opt_dmask, "dmask=%o"},  
  8.     {Opt_fmask, "fmask=%o"},  
  9.     {Opt_err, NULL}  
  10. };  
在解析mount选项的时候保存相应的值:

[cpp] view plain copy
 print?
  1. static int parse_options(char *options, struct super_block *sb)  
  2. {  
  3.       ...  
  4.       case Opt_uid:  
  5.             if (match_int(&args[0], &option))  
  6.                 return 0;  
  7.             sbi->s_uid = sbi->s_diskuid = option;  
  8.             break;  
  9.         case Opt_diskuid:  
  10.             if (match_int(&args[0], &option))  
  11.                 return 0;  
  12.             sbi->s_uid = option;  
  13.             if (match_int(&args[1], &option))  
  14.                 return 0;  
  15.             sbi->s_diskuid = option;  
  16.             break;  
  17.         case Opt_gid:  
  18.             if (match_int(&args[0], &option))  
  19.                 return 0;  
  20.             sbi->s_gid = sbi->s_diskgid = option;  
  21.             break;  
  22.         case Opt_diskgid:  
  23.             if (match_int(&args[0], &option))  
  24.                 return 0;  
  25.             sbi->s_gid = option;  
  26.             if (match_int(&args[1], &option))  
  27.                 return 0;  
  28.             sbi->s_diskgid = option;  
  29.             break;  
  30.         case Opt_dmask:  
  31.             if (match_octal(&args[0], &option))  
  32.                 return 0;  
  33.             sbi->fs_dmask = option;  
  34.             break;  
  35.         case Opt_fmask:  
  36.             if (match_octal(&args[0], &option))  
  37.                 return 0;  
  38.             sbi->fs_fmask = option;  
  39.             break;  
  40.       ...  
  41. }  
这样,相应的从外面 传进来的选项就已经可以解析并保存起来了,然后,就是要在读写inode的时候把它们相应的值转变过去:

fs/ext2/inode.c
在ext2_iget函数 中,添加ext2_fill_inode的调用如:

[cpp] view plain copy
 print?
  1. struct inode *ext2_iget (struct super_block *sb, unsigned long ino)  
  2. {  
  3.    ...  
  4.         inode->i_mode = le16_to_cpu(raw_inode->i_mode);  
  5.     inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);  
  6.     inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);  
  7.     ext2_fill_inode(sb, inode);  
  8.    ...  
  9. }  
还有static int __ext2_write_inode(struct inode *inode, int do_sync)函数中:

[cpp] view plain copy
 print?
  1. static int parse_options(char *options, struct super_block *sb)  
  2. {  
  3.    ...  
  4.    ext2_get_inode_flags(ei);  
  5.    ext2_fill_inode(sb, inode);  
  6.    ...  
  7.    if (!(test_opt(sb, NO_UID32))) {  
  8.         raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));  
  9.         raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));  
  10. /* 
  11.  * Fix up interopera.bility with old kernels. Otherwise, old inodes get 
  12.  * re-used with the upper 16 bits of the uid/gid intact 
  13.  */  
  14.         if (!ei->i_dtime) {  
  15.             raw_inode->i_uid_high = cpu_to_le16(high_16_bits(inode->i_uid));  
  16.             raw_inode->i_gid_high = cpu_to_le16(high_16_bits(inode->i_gid));  
  17.         } else {  
  18.             raw_inode->i_uid_high = 0;  
  19.             raw_inode->i_gid_high = 0;  
  20.         }  
  21.     } else {  
  22.         raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(inode->i_uid));  
  23.         raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(inode->i_gid));  
  24.         raw_inode->i_uid_high = 0;  
  25.         raw_inode->i_gid_high = 0;  
  26.     }  
这里都要做相应的更改,这样修改以后,挂载上去的文件的权限都及uid,gid都没有问题了,但是这个时候 我们发现新建文件还是会有问题,就是上面 列出来的,权限还是不对,这里还需要在创建文件或文件夹时做一些修改。

fs/ext2/namei.c

[cpp] view plain copy
 print?
  1. static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)  
  2. {  
  3.    ...  
  4.    inode = ext2_new_inode(dir, mode);  
  5.    ext2_fill_inode(dir->i_sb, inode);  
  6.    ...  
  7. }  
[cpp] view plain copy
 print?
  1. static int ext2_mkdir(struct inode * dir, struct dentry * dentry, int mode)  
  2. {  
  3.    ...  
  4.    inode = ext2_new_inode (dir, S_IFDIR | mode);  
  5.    ext2_fill_inode(dir->i_sb, inode  
  6.    ...  

这样,挂载的文件在android暂时就应该可以读写了,而且一般的操作应该是没问题,关于ext3、ext4的也跟这个类似,具体代码可以到下面这个链接去下载:

http://download.csdn.net/detail/new_abc/4226893

0 0
原创粉丝点击