1: 盘符 和 卷标的区别
通过代码就可以 U盘的基本信息 UUID 和 LABEL 都是通过 blkid 获取的。
之前被这个概念迷惑了很久, 走了不少弯路。
盘符 - window下的概念。 例如 C: 盘 D: 盘, C和D 这是就是盘符。 Linux下无对应的概念。
卷标 - 例如 C 盘如果命名为系统, D盘命名为电影, 系统和电影 这才是卷标。 Linux下也有这东西, 这个属于文件系统的部分。
2: Android 下如何获取卷标
StorageVolume.java 中的 public String getUserLabel() 获取。
3: Android现在支持的情况
如果这么简单获取那就方便了, 首先
StorageVolume.java 这个类是不公开的, 获取方法可以通过反射。
其次
public String getUserLabel()
这个方法, 底层和上层根本就没调通(Android4.4的原生代码部分, 我看是调试通过了)。
1: Vold 接收到 U 盘插入事件。
执行 Volume.cpp 的 int Volume::mountVol() 方法 这里调用
int Volume::extractMetadata(const char* devicePath)方法
。
/*
* Use blkid to extract UUID and label from device, since it handles many
* obscure edge cases around partition types and formats. Always broadcasts
* updated metadata values.
*/
int Volume::extractMetadata(const char* devicePath) {
int res = 0;
std::string cmd;
cmd = BLKID_PATH;
cmd += " -c /dev/null ";
cmd += devicePath;
FILE* fp = popen(cmd.c_str(), "r");
if (!fp) {
SLOGI("Failed to run %s: %s", cmd.c_str(), strerror(errno));
res = -1;
goto done;
}
char line[1024];
char value[128];
if (fgets(line, sizeof(line), fp) != NULL) {
SLOGI("blkid identified as %s", line);
char* start = strstr(line, "UUID=");
if (start != NULL && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
setUuid(value);
} else {
setUuid(NULL);
}
start = strstr(line, "LABEL=");
if (start != NULL && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
setUserLabel(value);
} else {
setUserLabel(NULL);
}
} else {
SLOGI("blkid failed to identify %s", devicePath);
res = -1;
}
pclose(fp);
done:
if (res == -1) {
setUuid(NULL);
setUserLabel(NULL);
}
return res;
}
4: blkid 分析
通过 static void print_tags(blkid_dev dev, char *show[], int numtag, int output) 把相关的信息进行输出。
5: blkid如何支持中文
这个就涉及到字符集相关的问题了, 说一个迷惑了我很久的字符集问题。
字符集包括unicode, gbk 以及gb2312等等,
但是utf-8, 这个东西不是字符集。这个是字符编码。
举个例子就明白啥叫字符编码了。
C中的字符串(char*)问题, 我们认为一个字符串的长度是, 读取到ASCII 0(‘/0’)的位置位置。
假设字符串 "A" 的GBK和UTF8编码都是 0x410 x00, 为啥后面多了个0x00, 这个就是字符串的结束位置。
字符A的 Unicode编码是 0x00 0x41, 如果用char*传递unicode字符串, 不知道字符串大小, 肯定是有问题的。 读到第一个0x00就结束了。
还不明白可以百度了。
对于vfat,fat32格式的U盘, 在windows下命名中文, 保存的字符编码是CP936(跟GBK差不多), 但是对于ntfs格式的u盘, 保存的方式是unicode。
这里涉及到android(linux)的编码问题, linux的默认编码是utf-8. 所以如果要正常显示, 需要在linux中合适的位置坐转码。
思路:
(只涉及中文, 韩文日文不考虑)在blkid这里把, 把编码直接从gbk转到utf8. (/external/e2fsprogs/misc/blkid.c)
特殊的ntfs获取卷标的地方, 为了上层的gbk编码兼容, 可以直接把unicode先转成gbk。(/external/e2fsprogs/lib/blkid/probe.c)
至于编码之间的转换可以参考网上的代码, 也可以使用开源的库iconv. 个人认为可以代码量比较小, 可以考虑网上的参考代码。