stat、fstat和lstat函数:
一旦给出pathname,stat函数返回与此函数命令文件有关的信息结构。第二个参数buf是指针,指向一个我们必须提供的结构体。该结构体的基本结构是:
文件类型:
1 普通文件(regular file):最常见的文件类型
2 目录文件(directory file):包含了其他文件的名字以及指向这些文件有关信息的指针,只有内核可以直接写目录文件
3 块特殊文件:提供对设备带缓冲的访问
4 字符特殊文件:提供对设备不带缓冲的访问
5 FIFO:用于进程通信,,有时也称为管道命令
6 套间字(socket):用于进程之间网络通信
7 符号连接:指向另一个文件
这些文件类型信息包含在stat结构的st_mode成员中
源代码:对每个命令行参数打印文件类型
#include "apue.h"
int
main(int argc, char *argv[])
{
int i;
struct stat buf;
char *ptr;
for (i = 1; i < argc; i++)
{
printf("%s: ", argv[i]);
if (lstat(argv[i], &buf) < 0) { //lstat函数,给出了路径名argv,就返回与此命令文件有关的信息结构,也就是返回给stat类型的buf
err_ret("lstat error");
continue;
}
if (S_ISREG(buf.st_mode)) //得到stat结构的buf中的st_mode,接下来用各种文件类型宏进行判断,输出对应信息
ptr = "regular";
else if (S_ISDIR(buf.st_mode))
ptr = "directory";
else if (S_ISCHR(buf.st_mode))
ptr = "character special";
else if (S_ISBLK(buf.st_mode))
ptr = "block special";
else if (S_ISFIFO(buf.st_mode))
ptr = "fifo";
else if (S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else if (S_ISSOCK(buf.st_mode))
ptr = "socket";
else
ptr = "** unknown mode **";
printf("%s\n", ptr);
}
exit(0);
}
新文件和目录的所有权
当用open或creat创建新文件时,并没有说明赋予的用户ID和组ID是什么,新文件的用户ID设置为进程的有效用户ID,组ID可以是进程的有效组ID,也可以是所在目录的组ID
access函数:
用open函数打开文件,以进程的有效用户ID和有效组ID为基础执行访问,access是按照实际用户ID和实际组ID进行访问权限设置的
chmod和fchmod函数:
两个函数可以让我们更改现有文件的访问权限。chmod在指定文件上进行操作,fchmod则对已打开的文件进行操作。而为了改变一个文件的权限位,进程的有效用户ID必须等于文件的所有者ID
chown,fchown和lchown函数
下列几个chown函数可用于更改文件的用户ID和组ID
文件的时间:
要注意数据最后修改时间和i节点最后更改时间的区别,前者是文件内容修改,后者是i节点内容修改,而很多操作会修改i节点,比如更改文件的访问权限,用户ID,连接数等。
但是并没有修改文件的实际内容。
而系统管理员常会删除哪些一段时间没有访问过的文件,最常见的比如a.out ,find命令常用在这些操作。
下表表示了各种函数对于这三种时间的影响
chdir,fchdir,getcwd函数
每个进程都有一个当前目录,当用户登陆unix系统时,当前目录一般是用户的起始目录(home),调用chdir和fchdir可以改变当前工作目录
因为当前工作目录是进程的一个属性,所以它只影响chdir本身,而不影响其他进程。
源代码;
#include "apue.h"
int main(void)
{
if (chdir("/tmp")<0)
err_sys("chdir faileed");
printf("chdir to /tmp succeeded");
exit(0);
}
运行结果执行这个程序的shell的当前工作目录并没有改变,原因是shell创建了一个子进程,由该子进程执行这个程序,由此可见,为了改变shell进程自己的工作目录,shell应该直接调用chdir函数,因此这个命令的执行程序应该直接包含在shell中。
可以采用getcwd函数来实现
当一个应用程序需要在文件系统中返回到其工作的起点时,getcwd是有用的。在更换工作目录 之前,用getcwd保存起来,在完成处理后,可将从getcwd获得的路径名作为调用参数传送给chdir。
#include "apue.h"
int main(void)
{
char *ptr;
int size;
if (chdir("/usr/spool/uucppbulic")<0)
err_sys("chdir failed");
ptr = path_alloc(&size);
if(getcwd(ptr,size) == NULL)
err_sys("getcwd failed");
printf("cwd = %s\n", ptr);
exit(0);
}
设备特殊文件:
st_dev和st_rdev这两个字段经常引起混淆,每个文件系统所在的储存设备都有主,次设备号表示,主设备号标识设备驱动程序,次设备号标识特定的子设备。
源代码:打印st_dev和st_rdev值
传递给程序的前两个参数是目录(/和/home/sar),后两个是设备名/dev/tty[01],也就是tty0和tty1,这两个设备是字符特殊设备。
从程序的输出可见,根目录和/home/sar目录的设备号不同,这表示他们位于不同的文件系统中。而两个终端设备是字符特殊文件,次设备号分别为4/0和4/1.