📄 lect08-bb.ppt
字号:
号的用户(也称为匿名FTP)放在一个单独的目录下,利用chroot将此目录当作新的<br>
根目录就可以阻止用户访问此目录以外的文件。<br>
chroot也用于在另一台机器上构造一文件系统层次结构的一个副本,然后修改此<br>
副本,但不更改原来的文件系统。这可用预测是新软件包装等场合。Chroot只能有<br>
超级用户使用,一旦更改了一个进程的root,该进程及其后代进程就再也不能恢复<br>
至原先的root。<br>
4.14 首先调用stat函数取得文件的三个时间值,然后调用utime设置期望的值。我<br>
们不希望在调用utime改变的值就是stat中相应的值。<br>
4.15 finger(1)对邮箱调用stat函数,最近一次的修改时间是上一次接收邮件的时<br>
间,最近访问时间是上一次读邮件的时间。<br>
4.16 对cpio来说,既可以改变文件的访问时间(st_atime)和修改时间(st_mtime)<br>
也可以都不改变。cpio的-a选项可以在读文件后重新设置文件的访问时间为读文件<br>
前的时间,所以cpio可以不改变文件的访问时间。另一方面,-m选项将文件的修改<br>
时间保存为原来的修改时间。<br>
对tar来说,在抽取文件时,其缺省方式是复原归档时的修改时间,但是-m选项则<br>
将修改时间设置为抽取文件时的时间。无论tar在何种情况,文件的访问时间均是<br>
抽取文件时的时间。<br>
由于不能修改状态改变时间(utime也只能改变访问时间和修改时间),所以没有将<br>
其保存在文档上。<br>
4.17 read改变了文件访问时间,为了消除这一影响,有些版本的file(1)调用uti<br>
me恢复文件的访问时间,但是这样做会修改文件的状态改变时间。<br>
4.18 内核对目录的深度没有内在的限制,但是如果路径名的长度超出了PATH_MAX<br>
有许多命令会失败。程序C.2创建了一个深度为100的目录树,每一级目录名有45个<br>
字符。利用getcwd可以得到第100级目录的绝对路径名(需要多次调用realloc申请<br>
一个足够大的缓存)。<br>
#include <sys/types.h><br>
#include <sys/stat.h><br>
#include <fcntl.h><br>
#include "ourhdr.h"<br>
#define DEPTH 100 /* directory depth */<br>
#define MYHOME "/home/stevens"<br>
#define NAME "alonglonglonglonglonglonglonglonglonglongname"<br>
int<br>
main(void)<br>
{<br>
int i, size;<br>
char *path;<br>
if (chdir(MYHOME) < 0)<br>
err_sys("chdir error");<br>
for (i = 0; i < DEPTH; i++) {<br>
if (mkdir(NAME, DIR_MODE) < 0)<br>
err_sys("mkdir failed, i = %d", i);<br>
if (chdir(NAME) < 0)<br>
err_sys("chdir failed, i = %d", i);<br>
}<br>
if (creat("afile", FILE_MODE) < 0)<br>
err_sys("creat error");<br>
/*<br>
* The deep directory is created, with a file at the leaf.<br>
* Now let's try and obtain its pathname.<br>
*/<br>
path = path_alloc(&size);<br>
for ( ; ; ) {<br>
if (getcwd(path, size) != NULL)<br>
break;<br>
else {<br>
err_ret("getcwd failed, size = %d", size);<br>
size += 100;<br>
if ( (path = realloc(path, size)) == NULL)<br>
err_sys("realloc error");<br>
}<br>
}<br>
printf("length = %d\n%s\n", strlen(path), path);<br>
exit(0);<br>
}<br>
程序C.2 创建深度目录<br>
运行后得到:<br>
$ a.out<br>
getcwd failed, size = 1025: Result too large<br>
getcwd failed, size = 1125: Result too large<br>
… { 33行}<br>
getcwd failed, size = 4525: Result too large<br>
length = 4613<br>
{显示4613字节的路径名}<br>
但是由于文件名太长了,不能用tar或cpio对该目录建立档案文件,而且也不能用<br>
rm -r命令删除该目录。(我们怎样才能删除该目录树?)<br>
4.19 /dev目录关闭了一般用户的写权限,所以用户不能删除目录中的文件,即un<br>
link失败。<br>
<br>
<br>
第五章<br>
5.2 fgets函数读入数据,直到行结束或缓冲区满(当然会留出一个字节存放'\0')<br>
。同样,fputs只负责将缓冲区的内容输出,而并不考虑缓冲区中是否包含换行符<br>
。所以,如果将MAXLINE设得很小,这两个函数仍然会正常工作,只不过被执行的<br>
次数要比MAXLINE值较大的时候多。<br>
5.3 当printf没有输出任何字符时,如:printf("") ,返回0。<br>
5.4 这是一个比较常见的错误。getc以及getchar的返回值是整型,而不是字符型<br>
。由于EOF经常定义为-1,那么如果系统使用的是有符号的字符类型,程序还可以<br>
正常工作。但如果使用的是无符号字符类型,那么返回的EOF被保存到字符c后将不<br>
再是-1,所以,程序会进入死循环。<br>
5.5 5个字符长的前缀、4个字符长的进程内唯一标识再加5个字符长的系统内唯一<br>
标识(进程ID)刚好组成14位的UNIX传统文件长度限制。<br>
5.6 使用方法为:先调用fflush后调用fsync,fsync所使用的参数由fileno函数获<br>
得。如果不调用fflush,所有的数据仍然在内存缓冲区中,此时调用fsync将没有<br>
任何效果。<br>
5.7 当程序交互运行时,标准输入输出设备均为行缓冲方式。每次调用fgets时标<br>
准输出设备将自动刷清。<br>
<br>
<br>
第六章<br>
6.1 在SVR4系统中,用户手册中讲述了获取阴影密码文件的函数。我们不能使用6<br>
.2节所述函数返回的pw_passwd变量来比较加密的口令。正确的方法是使用阴影密<br>
码文件中对应用户的加密口令来进行比较。<br>
在4.3+ BSD系统中,密码文件的阴影是自动建立的。仅当调用者的用户ID为0时,<br>
getpwnam或getpwuid函数返回的passed结构中的pw_passwd字段才包含有加密的口<br>
令。<br>
6.2 在SVR4系统中,程序C.3将输出加密的口令。当然,除非有超级用户权限,否<br>
则调用getspnam将返回EACCESS错误。<br>
#include <sys/types.h><br>
#include <shadow.h><br>
#include "ourhdr.h"<br>
int<br>
main(void) /* SVR4 version */<br>
{<br>
struct spwd *ptr;<br>
if ( (ptr = getspnam("stevens")) == NULL)<br>
err_sys("getspnam error");<br>
printf("sp_pwdp = %s\n",<br>
ptr->sp_pwdp == NULL || ptr->sp_pwdp[0] == 0 ?<br>
"(null)" : ptr->sp_pwdp);<br>
exit(0);<br>
}<br>
程序C.3 在SVR4系统中输出加密的口令<br>
在4.3+ BSD系统中,具有超级用户权限时,程序C.4将输出加密的口令。否则pw_<br>
passed的返回值为星号(*)。<br>
#include <sys/types.h><br>
#include <pwd.h><br>
#include "ourhdr.h"<br>
int<br>
main(void) /* 44BSD version */<br>
{<br>
struct passwd *ptr;<br>
if ( (ptr = getpwnam("stevens")) == NULL)<br>
err_sys("getpwnam error");<br>
printf("pw_passwd = %s\n",<br>
ptr->pw_passwd == NULL || ptr->pw_passwd[0] == 0<br>
<br>
?<br>
"(null)" : ptr->pw_passwd);<br>
exit(0);<br>
}<br>
程序C.4 在4.3+ BSD系统中输出加密的口令<br>
6.4<br>
#include <time.h><br>
#include "ourhdr.h"<br>
int<br>
main(void)<br>
{<br>
time_t caltime;<br>
struct tm *tm;<br>
char line[MAXLINE];<br>
if ( (caltime = time(NULL)) == -1)<br>
err_sys("time error");<br>
if ( (tm = localtime(&caltime)) == NULL)<br>
err_sys("localtime error");<br>
if (strftime(line, MAXLINE, "%a %b %d %X %Z %Y\n", tm) == 0)<br>
err_sys("strftime error");<br>
fputs(line, stdout);<br>
exit(0);<br>
}<br>
程序C.5 以date(1)的格式输出日期和时间<br>
程序C.5的运行结果如下:<br>
$ echo $TZ<br>
MST7<br>
$ a.out<br>
Wed Jan 15 06:48:57 MST 1992<br>
$ TZ=EST5EDT a.out U.S.East Coast<br>
Wed Jan 15 08:49:06 EST 1992<br>
$ TZ=JST-9 a.out Japan<br>
Wed Jan 15 22:49:12 JST 1992<br>
<br>
<br>
第七章<br>
7.1 原因在于printf的返回值(输出的字符数)变成了main函数的返回码。当然,并<br>
不是所有的系统都会出现该情况。<br>
7.2 当程序处于交互运行方式时,标准输出设备通常处于行缓冲方式,所以当键入<br>
新行符时,上次的结果才被真正输出。如果标准输出设备被定向到一个文件而处于<br>
完全缓冲方式,则当标准I/O清理操作执行时,结果才真正被输出。<br>
7.3 由于agrc和argv不象environ一样保存在全局变量中,所以在大多数Unix系统<br>
中没有其它办法。<br>
7.4 当C程序复引用一个空指针出错时,执行该程序的进程将终止,于是可以利用<br>
这种方法终止进程。<br>
7.5 定义如下:<br>
typedef void Exitfunc ( void ) ;<br>
int atexit ( Exitfunc *func ) ;<br>
7.6 calloc将分配的内存空间初始化为0。但是ANSI C并不保证0值与浮点0或空指<br>
针的值相同。<br>
7.7 只有通过exec函数执行一个程序时,才会分配堆和堆栈。<br>
7.8 可执行文件包含了用于调试core文件的符号表信息,用strip(1)可以删除这些<br>
信息,对两个a.out文件执行这条命令,它们的大小减为98304和16384。<br>
7.9 没有使用共享库时,可执行文件的大部分都被标准I/O库所占用。<br>
7.10 这段代码不正确。因为在if语句中定义了自动变量val,所以当if中的复合语<br>
句结束时,该变量就不存在了,但是在if语句之外又用指针引用已经不存在的自动<br>
变量val。<br>
第七章<br>
7.1 原因在于printf的返回值(输出的字符数)变成了main函数的返回码。当然,并<br>
不是所有的系统都会出现该情况。<br>
7.2 当程序处于交互运行方式时,标准输出设备通常处于行缓冲方式,所以当键入<br>
新行符时,上次的结果才
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -