shortname以及自动挂载
August 18th, 2009 | by vvoody |一切问题来自我前些天在优盘上搞的移动版的wiki(采用DokuWiki),插上优盘后,直接编辑我的wiki。但是发现有些页面是空白,功能不正常。后来发现是因为某些文件文件名在Linux下挂载后发生了变化,比如:”JSON.php”变成了”json.php”,造成了wiki无法正常运行 -______-!!
/etc/mtab显示有一个选项是shortname=lower,于是顺藤摸瓜google,发现通过手工挂载用参数shortname=mixed就正常。Linux下mount对fat/vfat文件系统(通常就是优盘的文件系统格式)默认挂载参数shortname的值就是lower。其实这个不太好,所有有人给了patch建议改成默认为shortname=mixed,可以看如下代码,更多见LKML里的讨论:
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 8970d8c..f9af501 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -971,7 +971,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->codepage = fat_default_codepage; opts->iocharset = fat_default_iocharset; if (is_vfat) { - opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; + opts->shortname = VFAT_SFN_DISPLAY_WINNT|VFAT_SFN_CREATE_WIN95; opts->rodir = 0; } else { opts->shortname = 0;
这个shortname参数都是因为有8.3文件名这种东西的存在而存在的,可以参考Wikipedia上的这篇文章。
还没完,每次手工挂载太蠢了。所以我想到了HAL,当时觉得可以改变默认的mount挂载参数(但事实不是)。还找到了如下的HAL policy:
<?xml version="1.0" encoding="UTF-8"?> <deviceinfo version="0.2"> <device> <match key="block.is_volume" bool="true"> <match key="volume.fsusage" string="filesystem"> <match key="volume.fstype" string="vfat"> <merge key="volume.policy.mount_option.shortname=" type="string">shortname=mixed</merge> </match> </match> </match> </device> </deviceinfo>
但是没有成功,lshal里看到了 volume.policy.mount_option.shortname= = ‘mixed’ (string) 这样的信息,可是我在Konqueror里打开仍然是以lower挂载的。在cppgx大牛的提醒和google到的这篇文章中,找到了两个原因:
- KDE这类DE会自己管理mount参数
- volume.policy.mount_option.shortname 这种写法已废弃
对于第一点,你可以在插上优盘后,打开Konqueror,到Storage Media里右击你的优盘盘符,属性里有一个挂载的标签,里面就有一些自定义的参数,其中就有shortname,而且默认就是lower。因此,如果你使用KDE,那么你可以在这个标签里将shortname改成mixed就可以正常显示优盘的文件名了。不过这不是全局的,你换了个优盘后,还得改一下。这些参数保存在~/.kde/share/config/mediamanagerrc
对于第二点,难怪在最新的hal-spec里打死找不到类似的方法。
到这里我才渐渐明白HAL是无法改变mount的挂载参数的,它可以发现硬件,然后提供给上层应用关于硬盘设备的很多信息,比如什么文件系统,可用的挂载参数等。像KDE这种能否自动挂载的,一定是从HAL那儿获得信息,然后有自己的程序去最终挂载设备,然后显示给用户。我很想看看KDE到底是怎么处理这些挂载参数的,所以经过一番长时间的搜索终于找到了相关代码(从没看过KDE代码,也不懂C++,而且觉得KDE网站搜索做的也不太好):
kdebase-3.5.10/kioslave/media/mediamanager/halbackend.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | QStringList HALBackend::mountoptions(const QString &name) { const Medium* medium = m_mediaList.findById(name); if (medium && !isInFstab(medium).isNull()) return QStringList(); // not handled by HAL - fstab entry KConfig config("mediamanagerrc"); config.setGroup(name); char ** array = libhal_device_get_property_strlist(m_halContext, name.latin1(), "volume.mount.valid_options", NULL); QMap<QString,bool> valids; for (int index = 0; array && array[index]; ++index) { QString t = array[index]; if (t.endsWith("=")) t = t.left(t.length() - 1); valids[t] = true; kdDebug() << "valid " << t << endl; } libhal_free_string_array(array); QStringList result; QString tmp; QString fstype = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.fstype"); if (fstype.isNull()) fstype = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.policy.mount_filesystem"); QString drive_udi = libhal_device_get_property_QString(m_halContext, name.latin1(), "block.storage_device"); bool removable = false; if ( !drive_udi.isNull() ) removable = libhal_device_get_property_bool(m_halContext, drive_udi.latin1(), "storage.removable", NULL) || libhal_device_get_property_bool(m_halContext, drive_udi.latin1(), "storage.hotpluggable", NULL); config.setGroup(drive_udi); bool value = config.readBoolEntry("automount", false); config.setGroup(name); if (libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_blank", NULL) || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_vcd", NULL) || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_svcd", NULL) || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.is_videodvd", NULL) || libhal_device_get_property_bool(m_halContext, name.latin1(), "volume.disc.has_audio", NULL)) value = false; result << QString("automount=%1").arg(value ? "true" : "false"); if (valids.contains("ro")) { value = config.readBoolEntry("ro", false); tmp = QString("ro=%1").arg(value ? "true" : "false"); if (fstype != "iso9660") // makes no sense result << tmp; } if (valids.contains("quiet")) { value = config.readBoolEntry("quiet", false); tmp = QString("quiet=%1").arg(value ? "true" : "false"); if (fstype != "iso9660") // makes no sense result << tmp; } if (valids.contains("flush")) { value = config.readBoolEntry("flush", fstype.endsWith("fat")); tmp = QString("flush=%1").arg(value ? "true" : "false"); result << tmp; } if (valids.contains("uid")) { value = config.readBoolEntry("uid", true); tmp = QString("uid=%1").arg(value ? "true" : "false"); result << tmp; } if ( valids.contains("locale") ) { value = config.readBoolEntry( "locale", true ); tmp = QString( "locale=%1" ).arg( value ? "true" : "false" ); result << tmp; } if (valids.contains("utf8")) { value = config.readBoolEntry("utf8", true); tmp = QString("utf8=%1").arg(value ? "true" : "false"); result << tmp; } if (valids.contains("shortname")) { QString svalue = config.readEntry("shortname", "lower").lower(); if (svalue == "winnt") result << "shortname=winnt"; else if (svalue == "win95") result << "shortname=win95"; else if (svalue == "mixed") result << "shortname=mixed"; else result << "shortname=lower"; } if (valids.contains("sync")) { value = config.readBoolEntry("sync", ( valids.contains("flush") && !fstype.endsWith("fat") ) && removable); tmp = QString("sync=%1").arg(value ? "true" : "false"); if (fstype != "iso9660") // makes no sense result << tmp; } if (valids.contains("noatime")) { value = config.readBoolEntry("atime", !fstype.endsWith("fat")); tmp = QString("atime=%1").arg(value ? "true" : "false"); if (fstype != "iso9660") // makes no sense result << tmp; } QString mount_point = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.mount_point"); if (mount_point.isEmpty()) mount_point = libhal_device_get_property_QString(m_halContext, name.latin1(), "volume.policy.desired_mount_point"); mount_point = config.readEntry("mountpoint", mount_point); if (!mount_point.startsWith("/")) mount_point = "/media/" + mount_point; result << QString("mountpoint=%1").arg(mount_point); result << QString("filesystem=%1").arg(fstype); if (valids.contains("data")) { QString svalue = config.readEntry("journaling").lower(); if (svalue == "ordered") result << "journaling=ordered"; else if (svalue == "writeback") result << "journaling=writeback"; else if (svalue == "data") result << "journaling=data"; else result << "journaling=ordered"; } return result; } |
第10行就是获取HAL提供的有效参数(lshal | grep valid_options);
第13到19行的for循环将各个参数放到valids数组中;
第21行的QStringList result;是所有参数/值对列表;
第92行就是和shortname有关的了。它先是读取配置文件~/.kde/share/config/mediamanagerrc中某个设备的shortname参数值,如果没有默认就是lower。看来KDE里处理shortname也是如此。
不过从上述代码来看,提供给KDE配置mount参数仍然不是很多,比如dmask、fmask等都没有。通过HAL还是可以添加所有的参数到valid_options。
* BTW,上述代码是KDE 3.5.10环境下的,KDE 4默认的shortname已经是mixed了。不过不再是mediamanager了,相关代码还没找到去看。
最后提供个方法修改mount任意挂载参数,以挂载vfat文件系统为例:
$ cat /sbin/mount.vfat #!/bin/sh /sbin/mount -i -t vfat -o umask=0000,fmask=0111,dmask=0000,shortname=mixed "$@"
注意,这是全局修改vfat的挂载参数。KDE最后还是调用mount挂载的设备,因此有了这个文件你就可以自定义KDE等不支持的参数了。
EOF
4 Responses to “shortname以及自动挂载”
By slackcode on Oct 21, 2009
Internet Explorer 6.0 Windows XP Internet Explorer 6.0 Windows XP你的高亮怎么弄上去的?
Reply
vvoody Reply:
Opera 9.80 Windows XPOctober 21st, 2009 at 15:00
wordpress的语法高亮插件 http://wordpress.org/extend/plugins/wp-syntax/
Reply
slackcode Reply:
Mozilla Firefox 3.5.3 Windows XPOctober 23rd, 2009 at 19:19
我觉得这个插件好像有点问题似的,我现在换了Typecho了
Reply
vvoody Reply:
Mozilla Firefox 3.5.3 LinuxOctober 23rd, 2009 at 22:03
Typecho是feelinglucky他们的项目吧?不是wordpress了啊。这个wp-syntax还发现大的问题,基本代码加亮都正常。
Reply