知识屋:更实用的电脑技术知识网站
所在位置:首页 > 操作系统 > linux

Linux/UNIX之文件和目录(1)

发布时间:2014-09-05 17:41:29作者:知识屋

文件和目录(1)

stat、fstat和lstat函数

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int stat(const char *path, struct stat*buf);

int fstat(int fd, struct stat *buf);

int lstat(const char *path, struct stat*buf);

一旦给出path,stat函数返回与词文件相关的信息结构。fstat获取已在描述符fd上打开的有关信息。lstat类似于stat,但当命名的文件是一个符号连接时,lstat返回该符号链接的有关信息,而不是该符号链接引用文件的信息。

第二个参数buf是一个结构指针,该结构返回文件有关信息,其基本形式如下:

struct stat {

dev_t st_dev; /* ID of device containing file */

ino_t st_ino; /* inode number */

mode_t st_mode; /* protection */

nlink_t st_nlink; /* number of hard links */

uid_t st_uid; /* user ID of owner */

gid_t st_gid; /* group ID of owner */

dev_t st_rdev; /* device ID (if special file) */

off_t st_size; /* total size, in bytes */

blksize_t st_blksize; /*blocksize for file system I/O */

blkcnt_t st_blocks; /* number of 512B blocks allocated */

time_t st_atime; /* time of last access */

time_t st_mtime; /* time of last modification */

time_t st_ctime; /* time of last status change */

};

文件类型

文件类型包括以下几种:

普通文件、目录文件、块特殊文件、字符特殊文件、FIFO、套接字和符号链接。

文件类型信息包含在stat结构的st_mode成员中,可用下面的宏来确定文件类型:

S_ISREG(): 普通文件

S_ISDIR(): 目录文件

S_ISCHR(): 字符特殊文件

S_ISBLK(): 块特殊文件

S_ISFIFO(): 管道或FIFO

S_ISLINK(): 符号链接

S_ISSOCK(): 套接字

如下程序取其命令参数,然后针对每一个命令参数打印其文件类型:

#include<unistd.h>

#include<stdio.h>

#include<sys/stat.h>

int main(int argc, char *argv[])

{

int i;

structstat buf;

char *ptr;

for(i = 1; i < argc; i++) {

printf("%s:", argv[i]);

if(lstat(argv[i], &buf) < 0) {

perror("lstaterror");

continue;

}

if(S_ISREG(buf.st_mode))

ptr= "regular";

elseif (S_ISDIR(buf.st_mode))

ptr= "directory";

elseif (S_ISCHR(buf.st_mode))

ptr= "character special";

elseif (S_ISBLK(buf.st_mode))

ptr= "block special";

elseif (S_ISFIFO(buf.st_mode))

ptr = "fifo";

elseif (S_ISLNK(buf.st_mode))

ptr= "symbolic link";

elseif (S_ISSOCK(buf.st_mode))

ptr= "socket";

else

ptr= "** unknown mode **";

printf("%s/n",ptr);

}

exit(0);

}

设置用户ID和设置组ID

每个进程相关联的ID有6个或更多,如下:

实际用户ID、实际组ID:我们实际上是谁

有效用户ID、有效组ID、附加组ID:用于文件访问权限的检查

保存的设置用户ID、保存的设置组ID:由exec函数保存

每个文件都有一个所有者和组所有者,所有者由stat结果中的st_uid成员表示,组所有者则由st_gid成员表示。

当执行一个程序文件时,进程的有效用户ID通常是实际用户ID,有效组ID通常是实际组ID。但可以在文件模式(st_mode)中可以通过设置用户ID位(S_ISUID)和设置组ID位(S_ISGID)将进程的有效用户ID设置为文件所有者的用户ID,将有效组ID设置为文件的组所有者的ID。

文件访问权限

st_mode值也包含了针对文件的访问权限位。

每个文件有9个访问权限,分为三类。chmod命令用于修改这9个权限值,改名了允许我们用u表示用户,用g表示组,用o表示其他。以下是9个访问权限位:

S_IRUSR 用户读

S_IWUSR 用户写

S_IXUSR 用户执行

S_IRGRP 用户读

S_IWGRP 用户写

S_IXGRP 用户执行

S_IROTH 用户读

S_IWOTH 用户写

S_IXOTH 用户执行

目录的读权限允许我们读目录,获得在该目录中所有文件名的列表。

当一个目录是我们要访问文件路径的一个组成部分时,对该目录的执行权限使我们可通过该目录。

当需要创建或删除有一个目录中的文件时,必须对包含该文件的目录具有写权限和执行权限。

进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试,这种测试可能涉及文件的所有者、进程的有效ID以及进程的附加组ID。两个所有者ID是文件的性质,而两个有效组ID和附加组ID则是进程的性质。内核测试如下:
1.若进程有效用户ID是0(超级用户),则允许访问

2.若进程有效用户ID等于文件所有者ID,那么可通过所有者设置适当的访问权限访问文件,否则拒绝访问。

3.若进程有效组ID或附加组ID等于文件组ID,那么可通过文件组设置的适当访问权限访问文件,否则拒绝访问。

4.若其他用户适当的访问权限被设置,则允许访问;否则拒绝访问。

创建新文件时,新文件的用户ID设置为进程的有效用户ID。关于组ID,POSIX.1允许实现选择下列之一作为新文件的组ID。

1) 新文件的组ID可以是进程的有效组ID

2) 新文件的组ID可以是它所在目录的组ID

access函数

#include <unistd.h>

int access(const char *pathname, int mode);

该函数按实际用户ID和实际组ID进行文件访问权限测试。成功返回0,出错返回-1。

其中第一个参数为测试文件名,第二个参数是以下所列常量的按位或

R_OK 测试读权限

W_OK 测试写权限

X_OK 测试执行权限

F_OK 测试文件是否存在

以下显示了access函数的使用方法:

#include "apue.h"

#include <fcntl.h>

int

main(int argc, char *argv[])

{

if (argc != 2)

err_quit("usage: a.out <pathname>");

if (access(argv[1], R_OK) < 0)

err_ret("access error for %s", argv[1]);

else

printf("read access OK/n");

if (open(argv[1], O_RDONLY) < 0)

err_ret("open error for %s", argv[1]);

else

printf("open for reading OK/n");

exit(0);

}

下面是该程序的示例会话:

chen123@ubuntu:~/user/apue.2e$ ls -l a.out

-rwxrwxr-x 1 chen123 chen123 78392014-04-18 19:59 a.out

chen123@ubuntu:~/user/apue.2e$ ./a.out a.out

read access OK

open for reading OK

chen123@ubuntu:~/user/apue.2e$ ls -l /etc/shadow

-rw-r----- 1 root shadow 1047 2014-04-1506:03 /etc/shadow

chen123@ubuntu:~/user/apue.2e$ ./a.out /etc/shadow

access error for /etc/shadow: Permissiondenied

open error for /etc/shadow: Permissiondenied

chen123@ubuntu:~/user/apue.2e$ su

Password:

root@ubuntu:/home/chen123/user/apue.2e# chown root a.out

root@ubuntu:/home/chen123/user/apue.2e# chmod u+s a.out

root@ubuntu:/home/chen123/user/apue.2e# ls -l a.out

-rwsrwxr-x 1 root chen123 7839 2014-04-1819:59 a.out

root@ubuntu:/home/chen123/user/apue.2e# exit

exit

chen123@ubuntu:~/user/apue.2e$ ./a.out /etc/shadow

access error for /etc/shadow: Permissiondenied

open for reading OK

这里的测试首先显示a.out的文件信息和/etc/shadow的文件信息。当执行./a.out /etc/shadow命令时,access不能通过,因为/etc/shadow的文件用户为root,而进程实际用户是chen123,所以没有读权限。open也不能通过,因为测试的是用户也是实际用户。但将a.out的用户ID改变为root,并打开设置用户ID位后,当执行a.out程序时,可以认为执行这个程序的进程有效用户ID变成了a.out文件用户ID root。但access函数测试的实际用户ID仍然是chen123。所以access不能通过,而open可以通过。但若没有打开设置用户ID位,open也不能通过。

umask函数

#include <sys/types.h>

#include <sys/stat.h>

mode_t umask(mode_t mask);

umask函数为进程设置文件模式创建屏蔽字,并返回以前的值。

参数mask是由文件访问权限中的9个常量中的若干个按位或构成的。在进程创建文件或新目录时,一定会使用文件模式创建屏蔽字。对于任何在文件模式创建屏蔽字中为1的为,在文件mode中的相应位一定被关闭。

chmod和fchmod函数

#include <sys/stat.h>

int chmod(const char *path, mode_t mode);

int fchmod(int fd, mode_t mode);

这两个函数可以更改现有的文件访问权限。

chown、fchown和lchown函数

#include <unistd.h>

int chown(const char *path, uid_t owner,gid_t group);

int fchown(int fd, uid_t owner, gid_tgroup);

int lchown(const char *path, uid_t owner,gid_t group);

以上函数可用于更改文件的用户ID和组ID。

在符号链接的情况下,lchown更改符号链接本身的所有者,而不是符号链接所指向的文件。

如若两个参数owner和group中的任意一个是-1,则个的ID不变。

文件长度

stat结构成员st_size表示一字节为单位的文件长度。此字段只对普通文件、目录文件和符号链接有意义。

对普通文件,其文件长度可以是0,在读这种文件时,将得到文件结束指示。

对于目录,文件长度通常是一个数(例如16或512)的倍数。

对于链接,文件长度是文件名(包括路径)中的实际字节数。

UNIX提供st_blksize字段,当我们将该字段用于读操作时,读一个文件的时间量最少。

文件截短

#include <unistd.h>

#include <sys/types.h>

int truncate(const char *path, off_tlength);

int ftruncate(int fd, off_t length);

这两个函数可以把现有的文件长度截短为length字节。如果该文件以前的长度大于length,则超过length以外的数据就不在能访问。如果以前的长度短语length,则扩张该文件,在旧文件尾端与新文件尾端填充0(也就是创建了空洞)。

讲一个文件清空为0可以在打开文件时使用O――TRUNC标志。

(免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)
收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜