用户交互输入--mtd-utils代码一例

昨天还说搞搞uboot,又搞搞MFC。今天又搞搞UBI。
有某个平台,使用UBI系统,工厂烧录回来的样片跑起来有问题,然后启动紧急预案。大有派我去某部门的意向——那个部门其实是单独在某地方,离公司不远,10多公里的路程,打的很快就到了。后面我坚持了远程操作的方法,手把手打字叫某兄弟怎么输入命令,最终找到一个临时解决方法。

闲话不多说,出现问题的提示如下:

1
2
ubiformat: warning!: 4 of 40 eraseblocks contain non-ubifs data
ubiformat: continue? (yes/no)

然后ubiformat等待用户输入yes,但测试时不可能手工输入,而且假如有N台设备出现这种情况,不可能一一输入的。程序死等,结果是内核狗超时设备复位。查代码,发现ubiformat有个y参数,强制认为所有的输入是yes,从而继续执行。后来想想,可以可能是没有进行擦除,导致检测失败。继续找代码,定位到一个libscan.c的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr));
if (ret < 0)
goto out_ec;

if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) {
if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) {
si->empty_cnt += 1;
si->ec[eb] = EB_EMPTY;
if (v)
printf(": empty\n");
} else {
si->alien_cnt += 1;
si->ec[eb] = EB_ALIEN;
if (v)
printf(": alien\n");
}
continue;
}

判断很简单,如果有某个数据(此时的我,对UBI了解不多,只能说“数据”)是全1的,就表示空块,EB_EMPTY,否则就标志为alien(非UBI块)。当有非UBI块时,就会报上面的问题。
(注:后来听说是工厂某兄弟没有把母片内容全部拷贝完。有这个可能,因为出错的分区位于flash很后面,而他们是直接拷贝的,有可能没有进行擦除操作,导致不是所有的数据都是1)
回到本文的正文,其实本文是想写写怎么和用户进行交互,用到哪些函数的。
用法很简单,示例代码如下:

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
typedef int bool;
#define true 1
#define false 0

/**
* prompt the user for confirmation
*/
static inline int prompt(const char *msg, int def)
{
char *line = NULL;
size_t len;
int ret = def;

do {
printf("%s (%c/%c) ", msg, def ? 'Y' : 'y', def ? 'n' : 'N');
fflush(stdout);

while (getline(&line, &len, stdin) == -1) {
printf("failed to read prompt; assuming '%s'\n",
def ? "yes" : "no");
break;
}

if (strcmp("\n", line) != 0) {
switch (rpmatch(line)) {
case 0: ret = false; break;
case 1: ret = true; break;
case -1:
puts("unknown response; please try again");
continue;
}
}
break;
} while (1);

printf("[debug] you input: %s\n", line);
free(line);

return ret;
}

// 当输入为no或n时,返回1
static int want_exit(void)
{
return prompt("continue?", false) == true ? 0 : 1;
}

// 当输入yes或y时,返回1
static int answer_is_yes(const char *msg)
{
return prompt(msg ? : "continue?", false);
}

// 当输入为no或n时,返回1
// 用途:判断返回值,当返回1时,说明是否定的操作,出错处理或退出
static int answer_is_no(const char *msg)
{
return prompt(msg, false) == true ? 0 : 1;
}

void test4()
{
int ret = 0;
printf("test for input ...\n");
ret = want_exit();
//ret = answer_is_yes("mark it as bad?");
//ret = answer_is_no("the answer will be no.");
printf("return: %d\n", ret);
}

我直接抄mtd-utils,稍改了一下。这个项目使用GPL,我贴出来,也当是遵循GPL了。

迟,记于2014.05.30