Unix/Linux编程实践教程 9.2分
读书笔记 2.6.3 问题3:如何编写cp
夏夜寂寞轻注销

原文有一段代码值得注意(出于调试需要,代码做了一点改动):

while((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0) { int write_res = write(out_fd, buf, n_chars); printf("%d\t%d\n", n_chars, write_res); if (write_res != n_chars) oops("Write error to ", av[2]); }
引自 第2章 用户、文件操作与联机帮助:编写 who 命令

测试环境是Ubuntu18.04,发现至少有两个问题使得编写的cp命令无法正常运行:

1. COPYMODE这个flag在Ubuntu18.04已经没用了(这个不对,具体请看补充说明),在open的帮助文档里面能找到对应的flag叫O_CREAT。如果仍旧沿用原代码,会有如下报错:Error: Cannot creat copy.of.cp: No such file or directory。

补充说明:有豆友在评论区做出了指正,还做了一些有用的补充。COPYMODE这个flag仍然有效,需要注意的是调用COPYMODE的api是creat而不是open。关于crate和open的区别可以看crate的manual page:creat() is equivalent to open() with flags equal to O_CREAT | O_WRONLY | O_TRUNC.

2. 基于1的前提,1所创建的新文件是有写操作保护的,所以改flag为O_CREAT仍然会报错Error: Cannot creat copy.of.cp: Permission denied。引用的代码加了一段printf分别查看n_chars和write(out_fd, buf, n_char)的值,分别为1000和-1,说明write函数调用失败,无法写入文件。

附一张图直接说明问题:

copy.of.cp没有读写的权限

前面的隐坑与文件访问模式和用户权限相关(这里假定你知道Linux文件用户权限的东西,不知道先找资料看看吧)。在这段代码当中,需要通过O_WRONLY增加对写入权限的支持,同时需要放开相应的读写权限。Stackoverflow上的答案有0777的黑魔法,不建议这么做,因为这么做就意味着创建的文件对任何人都开放读写权限,虽然实际操作不允许其他组用户做写入操作但是不要乱加权限!(可恶,这句能加粗我肯定加粗)保险起见,这里用0775。

#define OUTFDCHOMD 0775 if ((out_fd = open(av[2], O_CREAT | O_WRONLY, OUTFDCHOMD)) == -1)
引自 第2章 用户、文件操作与联机帮助:编写 who 命令

做完改动再编译代码运行,一切正常,用cmp比较两个文件没有提示,说明编写的cp指令达到了预期效果。

P.S. 发现《鸟哥的Linux私房菜》里对文件权限umask的讲解是不好理解的(不清楚其它讲解这方面的书会不会讲得更好),这里用更容易理解的方式讲一下:

这里,后三位775是八进制(Octal)数字,可以把它转换为三个一组的二进制(Binary)数字再理解,实际的拆分是

- | r | w | x | r | w | x | r | - | x

0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1

3
《Unix/Linux编程实践教程》的全部笔记 31篇
豆瓣
免费下载 iOS / Android 版客户端